//HeightMapInfo class
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework;
namespace TomShane.Neoforce.Central.Code
{
public class HeightMapInfo
{
#region Private fields
// TerrainScale is the distance between each entry in the Height property.
// For example, if TerrainScale is 30, Height[0,0] and Height[1,0] are 30
// units apart.
private float terrainScale;
// This 2D array of floats tells us the height that each position in the
// heightmap is.
private float[,] heights;
// the position of the heightmap's -x, -z corner, in worldspace.
private Vector3 heightmapPosition;
// the total width of the heightmap, including terrainscale.
private float heightmapWidth;
// the total height of the height map, including terrainscale.
private float heightmapHeight;
#endregion
// the constructor will initialize all of the member variables.
public HeightMapInfo(float[,] heights, float terrainScale)
{
if (heights == null)
{
throw new ArgumentNullException("heights");
}
this.terrainScale = terrainScale;
this.heights = heights;
heightmapWidth = (heights.GetLength(0) - 1) * terrainScale;
heightmapHeight = (heights.GetLength(1) - 1) * terrainScale;
heightmapPosition.X = -(heights.GetLength(0) - 1) / 2 * terrainScale;
heightmapPosition.Z = -(heights.GetLength(1) - 1) / 2 * terrainScale;
}
// This function takes in a position, and tells whether or not the position is
// on the heightmap.
public bool IsOnHeightmap(Vector3 position)
{
// first we'll figure out where on the heightmap "position" is...
Vector3 positionOnHeightmap = position - heightmapPosition;
// ... and then check to see if that value goes outside the bounds of the
// heightmap.
return (positionOnHeightmap.X > 0 &&
positionOnHeightmap.X < heightmapWidth &&
positionOnHeightmap.Z > 0 &&
positionOnHeightmap.Z < heightmapHeight);
}
// This function takes in a position, and returns the heightmap's height at that
// point. Be careful - this function will throw an IndexOutOfRangeException if
// position isn't on the heightmap!
// This function is explained in more detail in the accompanying doc.
public float GetHeight(Vector3 position)
{
// the first thing we need to do is figure out where on the heightmap
// "position" is. This'll make the math much simpler later.
Vector3 positionOnHeightmap = position - heightmapPosition;
// we'll use integer division to figure out where in the "heights" array
// positionOnHeightmap is. Remember that integer division always rounds
// down, so that the result of these divisions is the indices of the "upper
// left" of the 4 corners of that cell.
int left, top;
left = (int)positionOnHeightmap.X / (int)terrainScale;
top = (int)positionOnHeightmap.Z / (int)terrainScale;
// next, we'll use modulus to find out how far away we are from the upper
// left corner of the cell. Mod will give us a value from 0 to terrainScale,
// which we then divide by terrainScale to normalize 0 to 1.
float xNormalized = (positionOnHeightmap.X % terrainScale) / terrainScale;
float zNormalized = (positionOnHeightmap.Z % terrainScale) / terrainScale;
// Now that we've calculated the indices of the corners of our cell, and
// where we are in that cell, we'll use bilinear interpolation to calculuate
// our height. This process is best explained with a diagram, so please see
// the accompanying doc for more information.
// First, calculate the heights on the bottom and top edge of our cell by
// interpolating from the left and right sides.
float topHeight = MathHelper.Lerp(
heights[left, top],
heights[left + 1, top],
xNormalized);
float bottomHeight = MathHelper.Lerp(
heights[left, top + 1],
heights[left + 1, top + 1],
xNormalized);
// next, interpolate between those two values to calculate the height at our
// position.
return MathHelper.Lerp(topHeight, bottomHeight, zNormalized);
}
}
/// <summary>
/// This class will load the HeightMapInfo when the game starts. This class needs
/// to match the HeightMapInfoWriter.
/// </summary>
public class HeightMapInfoReader : ContentTypeReader<HeightMapInfo>
{
protected override HeightMapInfo Read(ContentReader input,
HeightMapInfo existingInstance)
{
float terrainScale = input.ReadSingle();
int width = input.ReadInt32();
int height = input.ReadInt32();
float[,] heights = new float[width, height];
for (int x = 0; x < width; x++)
{
for (int z = 0; z < height; z++)
{
heights[x, z] = input.ReadSingle();
}
}
return new HeightMapInfo(heights, terrainScale);
}
}
}

Edited July 2, 2014 by Landi20

0

Share this post

Link to post

Share on other sites

What does your project structure layout look like? Which projects/libraries have you created? Is the HeightmapCollisionPipeline stuff in its own project, and does your content project include a reference to that project?

i put like the example with exception this code i post

I don't understand what you mean. If there is an exception, you need to post what the exception says.