www.pudn.com > IntroductionTo3DGameEngineDesign.rar > Terrain.cs
using System;
using System.Drawing;
using Microsoft.DirectX;
using Microsoft.DirectX.Direct3D;
namespace GameEngine
{
public class TerrainQuad : Object3D, IDisposable
{
#region Attributes
private CustomVertex.PositionNormalTextured[] m_Corners;
private bool m_bValid = false;
public Vector3 m_Face1Normal;
public Vector3 m_Face2Normal;
public bool Valid { get { return m_bValid; } }
public Vector3 FaceNormals { get {
Vector3 sum = Vector3.Add(m_Face1Normal, m_Face2Normal);
sum.Normalize();
return sum; } }
#endregion
public TerrainQuad( string sName, Vector3 p1, Vector3 p2, Vector3 p3, Vector3 p4 ) : base( sName )
{
m_sName = sName;
// create the vertices for the box
m_Corners = new CustomVertex.PositionNormalTextured[6];
m_Corners[0].X = p3.X; // nw
m_Corners[0].Y = p3.Y;
m_Corners[0].Z = p3.Z;
m_Corners[0].Tu = 0.0f;
m_Corners[0].Tv = 1.0f;
m_Corners[1].X = p1.X; // sw
m_Corners[1].Y = p1.Y;
m_Corners[1].Z = p1.Z;
m_Corners[1].Tu = 0.0f;
m_Corners[1].Tv = 0.0f;
m_Corners[2].X = p4.X; // ne
m_Corners[2].Y = p4.Y;
m_Corners[2].Z = p4.Z;
m_Corners[2].Tu = 1.0f;
m_Corners[2].Tv = 1.0f;
m_Corners[3].X = p2.X; // ne
m_Corners[3].Y = p2.Y;
m_Corners[3].Z = p2.Z;
m_Corners[3].Tu = 1.0f;
m_Corners[3].Tv = 0.0f;
m_vPosition.X = (p4.X + p3.X) / 2.0f;
m_vPosition.Y = (p1.Y + p2.Y + p3.Y + p4.Y) / 4.0f;
m_vPosition.Z = (p1.Z + p3.Z) / 2.0f;
double dx = p4.X - p3.X;
double dz = p3.Z - p1.Z;
m_fRadius = (float)Math.Sqrt( dx * dx + dz * dz ) / 2.0f;
m_Face1Normal = GameMath.ComputeFaceNormal(
new Vector3(m_Corners[0].X,m_Corners[0].Y,m_Corners[0].Z),
new Vector3(m_Corners[1].X,m_Corners[1].Y,m_Corners[1].Z),
new Vector3(m_Corners[2].X,m_Corners[2].Y,m_Corners[2].Z) );
m_Face2Normal = GameMath.ComputeFaceNormal(
new Vector3(m_Corners[1].X,m_Corners[1].Y,m_Corners[1].Z),
new Vector3(m_Corners[3].X,m_Corners[3].Y,m_Corners[3].Z),
new Vector3(m_Corners[2].X,m_Corners[2].Y,m_Corners[2].Z) );
// default the vertex normals to the face normal value just in case
m_Corners[0].SetNormal( m_Face1Normal );
m_Corners[1].SetNormal( FaceNormals );
m_Corners[2].SetNormal( FaceNormals );
m_Corners[3].SetNormal( m_Face2Normal );
m_Corners[4].SetNormal( FaceNormals );
m_Corners[5].SetNormal( FaceNormals );
m_Corners[4].X = m_Corners[2].X;
m_Corners[4].Y = m_Corners[2].Y;
m_Corners[4].Z = m_Corners[2].Z;
m_Corners[4].Tu = m_Corners[2].Tu;
m_Corners[4].Tv = m_Corners[2].Tv;
m_Corners[5].X = m_Corners[1].X;
m_Corners[5].Y = m_Corners[1].Y;
m_Corners[5].Z = m_Corners[1].Z;
m_Corners[5].Tu = m_Corners[1].Tu;
m_Corners[5].Tv = m_Corners[1].Tv;
m_bValid = true;
}
public void SetCornerNormal( int Corner, Vector3 Normal )
{
Normal.Normalize();
m_Corners[Corner].SetNormal( Normal );
}
public override void Dispose()
{
}
public int RenderQuad( int Offset, CustomVertex.PositionNormalTextured[] vertices )
{
int newOffset = Offset;
if ( Valid && !IsCulled )
{
for ( int i=0; i<6; i++ )
{
vertices[Offset+i] = m_Corners[i];
}
newOffset += 6;
Culled = true;
}
return newOffset;
}
public override bool InRect( Rectangle rect )
{
bool inside = false;
// check to see if the object is within this rectangle by checking each corner
for ( int i=0; i<4; i++ )
{
if ( rect.Contains((int)m_Corners[i].X,(int)m_Corners[i].Z) )
{
inside = true;
break;
}
}
return inside;
}
}
///
/// Summary description for Terrain.
///
public class Terrain : IDisposable, ITerrainInfo
{
private Vector3[,] m_Elevations;
private VertexBuffer m_VB = null; // Vertex buffer
private TerrainQuad[,] m_Quads = null;
private int m_xSize;
private int m_ySize;
private Texture m_Texture; // image for face
private bool m_bValid = false;
private CustomVertex.PositionNormalTextured[] m_Vertices;
private float m_Spacing;
public Terrain(int xSize, int ySize, string sName, string sTexture, float fSpacing, float fElevFactor)
{
int nTemp;
m_Elevations = new Vector3[xSize,ySize];
m_xSize = xSize-1;
m_ySize = ySize-1;
m_Quads = new TerrainQuad[m_xSize,m_ySize];
m_Vertices = new CustomVertex.PositionNormalTextured[3000];
m_Spacing = fSpacing;
try
{
System.Drawing.Bitmap bmp = new System.Drawing.Bitmap(sName);
for ( int i=0; i 0.0 )
{
attitude.Pitch = (float)(Math.PI/2.0) - attitude.Pitch;
}
else
{
attitude.Pitch = -((float)(Math.PI/2.0) + attitude.Pitch);
}
}
if ( attitude.Pitch > (Math.PI/4.0) || attitude.Pitch < -(Math.PI/4.0) )
{
Console.AddLine("Pitch " + attitude.Pitch*180.0/Math.PI + " " + normal.ToString());
}
if ( normal.X == 0.0f )
{
attitude.Roll = 0.0f;
}
else
{
attitude.Roll = -(float)Math.Atan(normal.Y/normal.X);
if ( attitude.Roll > 0.0 )
{
attitude.Roll = (float)(Math.PI/2.0) - attitude.Roll;
}
else
{
attitude.Roll = -((float)(Math.PI/2.0) + attitude.Roll);
}
}
if ( attitude.Roll > (Math.PI/4.0) || attitude.Roll < -(Math.PI/4.0) )
{
Console.AddLine("Roll " + attitude.Roll*180.0/Math.PI + " " + normal.ToString());
}
attitude.Heading = Heading;
return attitude;
}
public void Render( Camera cam )
{
int nQuadsDrawn = 0;
if ( m_bValid )
{
CGameEngine.Device3D.RenderState.CullMode = Cull.Clockwise;
CGameEngine.Device3D.VertexFormat = CustomVertex.PositionNormalTextured.Format;
Material mtrl = new Material();
mtrl.Ambient = Color.White;
mtrl.Diffuse = Color.White;
CGameEngine.Device3D.Material = mtrl;
// Set the texture
CGameEngine.Device3D.SetTexture(0, m_Texture );
// Set the matrix for normal viewing
Matrix matWorld = new Matrix();
matWorld = Matrix.Identity;
CGameEngine.Device3D.Transform.World = matWorld;
CGameEngine.Device3D.Transform.View = cam.View;
int Offset = 0;
for ( int i=0; i= 2990 )
{
CGameEngine.Device3D.VertexFormat = CustomVertex.PositionNormalTextured.Format;
m_VB.SetData(m_Vertices, 0, 0);
CGameEngine.Device3D.SetStreamSource( 0, m_VB, 0 );
CGameEngine.Device3D.DrawPrimitives( PrimitiveType.TriangleList, 0, Offset/3 );
nQuadsDrawn += Offset / 6;
Offset = 0;
}
}
catch
{
Console.AddLine("Error rendering terrain quad " + i + "," + j);
}
}
}
if ( Offset > 0 )
{
try
{
CGameEngine.Device3D.VertexFormat = CustomVertex.PositionNormalTextured.Format;
m_VB.SetData(m_Vertices, 0, 0);
CGameEngine.Device3D.SetStreamSource( 0, m_VB, 0 );
CGameEngine.Device3D.DrawPrimitives( PrimitiveType.TriangleList, 0, Offset/3 );
nQuadsDrawn += Offset / 6;
Offset = 0;
}
catch (DirectXException d3de)
{
Console.AddLine("Unable to render terrain " );
Console.AddLine(d3de.ErrorString);
}
catch ( Exception e )
{
Console.AddLine("Unable to render terrain" );
Console.AddLine(e.Message);
}
}
}
}
public void Dispose()
{
for ( int i=0; i