I also created my own shader for the terrain as I found that Riemers, although very good as it had great detail, slowed my engine a little. The shader I came up with, while not being as pretty gives a faster render, I will put that up here to.
So on to the code. What I will do is break it down into chunks again and then offer the whole class at the end. I am not going to go over the basic terrain code as this is all covered in Riemers tutorial, for this please go to his site and read though the tutorial to get a better understanding, saves me repeating his tutorial. Also there are some methods I have commented out as they are unfinished, for example I am working on a random map generator, this is not complete so has been removed, also there is the color map generator for the terrain, this I have left as it is completed, but it was more of a folly rather than for any real purpose, I have left it in as a matter of completeness.
Terrain Position
private Vector3 basePosition;
public new Vector3 Position
{
get { return basePosition; }
set { basePosition = value; }
}
public new Vector3 Position
{
get { return basePosition; }
set { basePosition = value; }
}
GetHeightAt
public Vector3 GetHeightAt(Vector3 objPosition)
{
Vector3 retVal = new Vector3();
int x, y;
y = (int)objPosition.X + (myWidth / 2);
x = (int)objPosition.Z + (myHeight / 2);
if ((x >= 0 && y >= 0) && (x < myWidth && y < myHeight))
retVal = new Vector3(x, y, myPosition.Y + myHeightData[x, y]);
return retVal;
}
{
Vector3 retVal = new Vector3();
int x, y;
y = (int)objPosition.X + (myWidth / 2);
x = (int)objPosition.Z + (myHeight / 2);
if ((x >= 0 && y >= 0) && (x < myWidth && y < myHeight))
retVal = new Vector3(x, y, myPosition.Y + myHeightData[x, y]);
return retVal;
}
Collision
public bool Collision(Vector3 objPosition, float heightBuffer)
{
bool retVal = false;
int x, y, objHeight;
y = (int)objPosition.X + (myWidth / 2);
x = (int)objPosition.Z + (myHeight / 2);
objHeight = (int)(objPosition.Y - heightBuffer);
if ((x >= 0 && y >= 0) && (x < myWidth && y < myHeight))
{
if (objHeight < myPosition.Y + myHeightData[x, y])
retVal = true;
}
return retVal;
}
Here is an example of this in action, this code placed in the Update of your Game will stop your camera from going through the terrain and give it the impression of being solid.
// Terrain collision.
RCTerrain terrain = (RCTerrain)(((RCObjectNode)game.Scene.GetObject("terrain")).Object);
game.WriteText(game.Font, 10, 100, terrain.GetHeightAt(RCCameraManager.ActiveCamera.Position).ToString(), Color.White);
if (terrain.Collision(RCCameraManager.ActiveCamera.Position, 2.5f))
RCCameraManager.ActiveCamera.Position = new Vector3(RCCameraManager.ActiveCamera.Position.X, RCCameraManager.ActiveCamera.Position.Y + .2f, RCCameraManager.ActiveCamera.Position.Z);
RCTerrain terrain = (RCTerrain)(((RCObjectNode)game.Scene.GetObject("terrain")).Object);
game.WriteText(game.Font, 10, 100, terrain.GetHeightAt(RCCameraManager.ActiveCamera.Position).ToString(), Color.White);
if (terrain.Collision(RCCameraManager.ActiveCamera.Position, 2.5f))
RCCameraManager.ActiveCamera.Position = new Vector3(RCCameraManager.ActiveCamera.Position.X, RCCameraManager.ActiveCamera.Position.Y + .2f, RCCameraManager.ActiveCamera.Position.Z);
PickTerrain
Before Mouse Clicks
After wasfting the mouse, clicking left and right mouse buttons
public void PickTerrain(GraphicsDevice device, Point mousecoords, bool Up)
{
RCCameras.RCCamera camera = RCCameras.RCCameraManager.ActiveCamera;
Vector3 nearSource = camera.Viewport.Unproject(new Vector3(mousecoords.X, mousecoords.Y, camera.Viewport.MinDepth), camera.Projection, camera.View, Matrix.Identity);
Vector3 farSource = camera.Viewport.Unproject(new Vector3(mousecoords.X, mousecoords.Y, camera.Viewport.MaxDepth), camera.Projection, camera.View, Matrix.Identity);
Vector3 direction = farSource - nearSource;
float zFactor = nearSource.Y / direction.Y;
Vector3 zeroWorldPoint = nearSource + direction * zFactor;
Ray ray = new Ray(nearSource, direction);
for (int x = 0; x < myWidth; x++)
for (int y = 0; y < myHeight; y++)
{
BoundingBox tmp = new BoundingBox(myVertices[x + y * myWidth].Position + myPosition, (myVertices[x + y * myWidth].Position + myPosition) + new Vector3(1f, 1f, 1f));
if (ray.Intersects(tmp) != null)
{
float val = 0;
if (Up)
val += .5f;
else
val -= .5f;
if (x > 0)
myHeightData[x - 1, y] += val;
myHeightData[x, y] += val;
if (x < myWidth)
myHeightData[x + 1, y] += val;
if (x > 0 && y > 0)
myHeightData[x - 1, y - 1] += val;
if (y > 0)
myHeightData[x, y - 1] += val;
if (x < myWidth && y > 0)
myHeightData[x + 1, y - 1] += val;
if (x > 0 && y < myHeight)
myHeightData[x - 1, y + 1] += val;
if (y < myHeight)
myHeightData[x, y + 1] += val;
if (x < myWidth && y < myHeight)
myHeightData[x + 1, y + 1] += val;
break;
}
}
BuildTerrain(device);
}
{
RCCameras.RCCamera camera = RCCameras.RCCameraManager.ActiveCamera;
Vector3 nearSource = camera.Viewport.Unproject(new Vector3(mousecoords.X, mousecoords.Y, camera.Viewport.MinDepth), camera.Projection, camera.View, Matrix.Identity);
Vector3 farSource = camera.Viewport.Unproject(new Vector3(mousecoords.X, mousecoords.Y, camera.Viewport.MaxDepth), camera.Projection, camera.View, Matrix.Identity);
Vector3 direction = farSource - nearSource;
float zFactor = nearSource.Y / direction.Y;
Vector3 zeroWorldPoint = nearSource + direction * zFactor;
Ray ray = new Ray(nearSource, direction);
for (int x = 0; x < myWidth; x++)
for (int y = 0; y < myHeight; y++)
{
BoundingBox tmp = new BoundingBox(myVertices[x + y * myWidth].Position + myPosition, (myVertices[x + y * myWidth].Position + myPosition) + new Vector3(1f, 1f, 1f));
if (ray.Intersects(tmp) != null)
{
float val = 0;
if (Up)
val += .5f;
else
val -= .5f;
if (x > 0)
myHeightData[x - 1, y] += val;
myHeightData[x, y] += val;
if (x < myWidth)
myHeightData[x + 1, y] += val;
if (x > 0 && y > 0)
myHeightData[x - 1, y - 1] += val;
if (y > 0)
myHeightData[x, y - 1] += val;
if (x < myWidth && y > 0)
myHeightData[x + 1, y - 1] += val;
if (x > 0 && y < myHeight)
myHeightData[x - 1, y + 1] += val;
if (y < myHeight)
myHeightData[x, y + 1] += val;
if (x < myWidth && y < myHeight)
myHeightData[x + 1, y + 1] += val;
break;
}
}
BuildTerrain(device);
}
[Class and shader was here, but can't post it, please see original blog post]
Well I guess my Water class is next, here is an image of it in action:
First some nice calm water, waves at an amplitude of .1
Now at amplitude 1
"lets go surfing now, everybody's learning how..."
Posted Mon, Oct 15 2007 2:59 PM by Charles Humphrey | Add post to favorites | Add blog to favorites
Filed under: Randomchaos 3D Engine, Terrain, XNA 1.0 [Edit Tags]
No comments:
Post a Comment