using System;
using System.IO;
using System.Drawing;
using System.Collections;
using System.ComponentModel;
using System.Windows.Forms;
using System.Data;
using Microsoft.DirectX;
using Microsoft.DirectX.Direct3D;
using Microsoft.DirectX.DirectInput;
namespace TerrainMapper
{
/// <summary>
/// Summary description for Form1.
/// </summary>
public class Form1 : System.Windows.Forms.Form
{
/// <summary>
/// Required designer variable.
/// </summary>
private System.ComponentModel.Container components = null;
private Microsoft.DirectX.Direct3D.Device device = null;
private float angle = 0.3f;
private float UD = 0.3f;
private VertexBuffer vb;
private IndexBuffer ib = null;
private int TWIDTH = 128;
private int THEIGHT = 128;
private int [] indices;
private int[,] HeightMap;
private FileStream fs;
private BinaryReader br;
private CustomVertex.PositionColored[] verts;
private bool FullScreen = true;
private Microsoft.DirectX.DirectInput.Device keyb;
public Form1()
{
//
// Required for Windows Form Designer support
//
InitializeComponent();
this.SetStyle(ControlStyles.AllPaintingInWmPaint | ControlStyles.Opaque, true);
}
/// <summary>
/// Clean up any resources being used.
/// </summary>
protected override void Dispose( bool disposing )
{
if( disposing )
{
if (components != null)
{
components.Dispose();
}
}
base.Dispose( disposing );
}
#region Windows Form Designer generated code
/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
private void InitializeComponent()
{
//
// Form1
//
this.AutoScaleBaseSize = new System.Drawing.Size(5, 13);
this.ClientSize = new System.Drawing.Size(292, 273);
this.Name = "Form1";
this.Text = "Form1";
this.Load += new System.EventHandler(this.Form1_Load);
}
#endregion
/// <summary>
/// The main entry point for the application.
/// </summary>
[STAThread]
public void InitializeGraphics()
{
//Setup Device Perameters
PresentParameters prams = new PresentParameters();
//ShowProgram in window
prams.Windowed = ! FullScreen;
prams.SwapEffect = SwapEffect.Discard;
if ( FullScreen)
{
prams.BackBufferCount = 1;
prams.BackBufferFormat = Format.X8R8G8B8;
prams.BackBufferWidth = 800;
prams.BackBufferHeight = 600;
}
//Enable Depth(z) buffering
// Create Device, Set Hardware mode and software vertex processing
device = new Microsoft.DirectX.Direct3D.Device(0,Microsoft.DirectX.Direct3D.DeviceType.Hardware,this,CreateFlags.SoftwareVertexProcessing, prams);
//WireFrame Mode
device.RenderState.FillMode = FillMode.WireFrame;
//No culling
device.RenderState.CullMode = Cull.None;
}
protected override void OnPaint(System.Windows.Forms.PaintEventArgs e)
{
// Set background to black
device.Clear(ClearFlags.Target, Color.Black, 1.0f,0);
device.BeginScene();
device.VertexFormat = CustomVertex.PositionColored.Format;
//Read from Vetex Buffer
device.SetStreamSource(0,vb,0);
//Tell device where the Index Buffer is;
device.Indices = ib;
device.Transform.World = Matrix.Translation(-THEIGHT/2, -TWIDTH/2,0)*Matrix.RotationZ(angle)*Matrix.RotationX(UD);
device.DrawIndexedPrimitives(PrimitiveType.TriangleList,0,0, TWIDTH*THEIGHT,0, indices.Length/3);
//Draws from Index Buffer.
device.EndScene();
device.Present();
this.Invalidate();
ReadKeyboard();
}
private void SetupCamera()
{
device.Transform.Projection = Matrix.PerspectiveFovLH((float)Math.PI/4, this.Width/this.Height, 1f, 150f);
device.Transform.View = Matrix.LookAtLH(new Vector3(0,-80,90), new Vector3(0,-5,0), new Vector3(0,1,0));
//Switch of lighting as there are no normals to reflect light
device.RenderState.Lighting = false;
//Switch culling off
device.RenderState.CullMode = Cull.None;
}
private void Form1_Load(object sender, System.EventArgs e)
{
}
public void LoadMapData()
{
//Setup HeightMap data
HeightMap = new int[TWIDTH,THEIGHT];
//Open a Filestream
fs = new FileStream(@"..\..\HeightMap.RAW",FileMode.Open, FileAccess.Read);
//Create a binary reader
br = new BinaryReader(fs);
//Loop through .RAW file and assign data to HeightMap
for(int x = 0; x< THEIGHT; x++)
{
for(int y = 0; y <TWIDTH; y++)
{
int h =(int)(br.ReadByte()/5);
HeightMap[TWIDTH-1-y,THEIGHT-1-x] = h;
}
}
br.Close();
}
public void VertexSetup()
{
//Setup Vertex Buffer
vb = new VertexBuffer(typeof(CustomVertex.PositionColored), TWIDTH*THEIGHT,device, Usage.Dynamic | Usage.WriteOnly, CustomVertex.PositionColored.Format, Pool.Default);
//vb.Created += new EventHandler (this.OnVbCreate);
//OnVbCreate(vb,null);
//Setup Vertex Array
verts = new CustomVertex.PositionColored[TWIDTH*THEIGHT];
//Move through loop asigning values to verticies
for (int x=0;x<TWIDTH;x++)
{
for (int y=0; y<THEIGHT;y++)
{
verts[x+y*TWIDTH].SetPosition(new Vector3(x, y, HeightMap[x,y]));
verts[x+y*TWIDTH].Color = Color.White.ToArgb();
}
}
//Consine data to vertex buffer
vb.SetData(verts,0,LockFlags.None);
}
public void IndexSetup()
{
//Setup Index Buffer
ib = new IndexBuffer (typeof(int), (TWIDTH-1)*(THEIGHT-1)*6, device, Usage.WriteOnly, Pool.Default);
//ib.Created+= new EventHandler(this.OnIbCreate);
//OnIbCreate(ib,null);
//Setup array of indexed vertexes
indices = new int [(TWIDTH-1)*(THEIGHT-1)*6];
// Loop through and assign indexed vertexes
for (int x=0;x<TWIDTH-1;x++)
{
for (int y=0; y<THEIGHT-1;y++)
{
indices[(x+y*(TWIDTH-1))*6] = (x+1)+(y+1)*TWIDTH;
indices[(x+y*(TWIDTH-1))*6+1] = (x+1)+y*TWIDTH;
indices[(x+y*(TWIDTH-1))*6+2] = x+y*TWIDTH;
indices[(x+y*(TWIDTH-1))*6+3] = (x+1)+(y+1)*TWIDTH;
indices[(x+y*(TWIDTH-1))*6+4] = x+y*TWIDTH;
indices[(x+y*(TWIDTH-1))*6+5] = x+(y+1)*TWIDTH;
}
}
ib.SetData(indices, 0, LockFlags.None);
}
public void InitializeKeyboard()
{
keyb = new Microsoft.DirectX.DirectInput.Device(SystemGuid.Keyboard);
keyb.SetCooperativeLevel(this, CooperativeLevelFlags.Background | CooperativeLevelFlags.NonExclusive);
keyb.Acquire();
}
private void ReadKeyboard()
{
KeyboardState keys = keyb.GetCurrentKeyboardState();
if (keys[Key.LeftArrow])
{
angle+=0.03f;
}
if (keys[Key.RightArrow])
{
angle-=0.03f;
}
if (keys[Key.UpArrow])
{
UD+=0.03f;
}
if (keys[Key.DownArrow])
{
UD-=0.03f;
}
if (keys[Key.Escape])
{
this.Close();
}
}
static void Main()
{
using(Form1 frm = new Form1())
{
frm.InitializeGraphics();
frm.InitializeKeyboard();
frm.SetupCamera();
frm.LoadMapData();
frm.VertexSetup();
frm.IndexSetup();
frm.Show();
try
{
Application.Run(frm);
}
catch(Exception e)
{
}
}
}
}
}
Getting Normals from a height map(C#)
thanks to the superb tutorial @ http://users.pandora.be/riemer/index.html i have managed to get a heightmap reading program running :)
Now i need a way to calculate normals for the wireframe mesh
I could use a link to a tutorial or if its simple enough to explain then please feel free :)
If its of any help here is my code:
Hello again.
I couldn't recall any great terrain normal tutorials, but I googled this and it looks pretty good, and to the point.
If you know anything about vector math, you'll be way ahead. Basically, by constructing two vectors from the three points of a triangle and doing a cross product operation, you can obtain a vector that is perpindicular to both vectors on the triangle, or normal to the triangle. Even if you don't understand the concept of vectors, there's some reduced math given on the above page, although I suggest you learn about vectors in the long run.
The problem you run into with a separate face normal for each triangle is that each polygon shows up distinctly in the presence of a light source. The solution is to specify vertex normals. This is analogous to drawing a triangle with each vertex having a different color. The result is a blending of light reflectivity across each triangle, making the terrain [appear] smoother.
Long story short, each vertex normal is a sum of each surrounding triangle's face normal.
Sorry if that was too much/not enough information. Maybe someone else has a better article bookmarked somewhere, since I don't know how good this one is.
Edit: And don't forget to normalize your vectors!
I couldn't recall any great terrain normal tutorials, but I googled this and it looks pretty good, and to the point.
If you know anything about vector math, you'll be way ahead. Basically, by constructing two vectors from the three points of a triangle and doing a cross product operation, you can obtain a vector that is perpindicular to both vectors on the triangle, or normal to the triangle. Even if you don't understand the concept of vectors, there's some reduced math given on the above page, although I suggest you learn about vectors in the long run.
The problem you run into with a separate face normal for each triangle is that each polygon shows up distinctly in the presence of a light source. The solution is to specify vertex normals. This is analogous to drawing a triangle with each vertex having a different color. The result is a blending of light reflectivity across each triangle, making the terrain [appear] smoother.
Long story short, each vertex normal is a sum of each surrounding triangle's face normal.
Sorry if that was too much/not enough information. Maybe someone else has a better article bookmarked somewhere, since I don't know how good this one is.
Edit: And don't forget to normalize your vectors!
Thanks PiE3 your a Star & you get a big 5 rating from me :)
Your spot on with all the links you've been posting... Top Stuff.
Your spot on with all the links you've been posting... Top Stuff.
Quote:Original post by JDUK
Thanks PiE3 your a Star & you get a big 5 rating from me :)
Your spot on with all the links you've been posting... Top Stuff.
No problem.
I almost forgot about the Vertex3 class you can use with Managed DirectX. You can do cross product multiplication and normalization within the Vector3 class, although I still suggest you learn what's behind it.
Good Luck!
Ok im back after reading the links you sent me and the material on normals in "3D games Realtime rendering and software technology".
I have read a program that compiles and works that that uses this to calculate the normals
From what i have read the calculation u need to perform beforeyou get the cross porduct is:
v1 = t2 - t1
v2 = t3 - t1
so i would assume in the above code that when assigning data to X & Z that you would:
Vector3.Subtract(t2,t1)
&
Vector3.Subtract(t3,t1)
t1 being the same in both calculaitons, BUT thier not . The program the code above is from compiles and looks great.
So have i misunderstood the
v1 = t2 - t1
v2 = t3 - t1
part or is the above code doing it a different way?
I could REALLY use some help clearing this up.
Thanks.
[/source]
I have read a program that compiles and works that that uses this to calculate the normals
for ( int i = 1; i < numHeight-1; i ++) { for ( int j = 1; j < numWidth-1; j ++) { // Calculate the real normals by using the cross product of the vertex' neighbours Vector3 X = Vector3.Subtract(verts[i*numWidth+j+1].Position,verts[i*numWidth+j-1].Position); Vector3 Z = Vector3.Subtract(verts[(i+1)*numWidth+j].Position,verts[(i-1)*numWidth+j].Position); Vector3 Normal = Vector3.Cross(Z,X); Normal.Normalize(); verts[i*numWidth+j].Normal = Normal; } }
From what i have read the calculation u need to perform beforeyou get the cross porduct is:
v1 = t2 - t1
v2 = t3 - t1
so i would assume in the above code that when assigning data to X & Z that you would:
Vector3.Subtract(t2,t1)
&
Vector3.Subtract(t3,t1)
t1 being the same in both calculaitons, BUT thier not . The program the code above is from compiles and looks great.
So have i misunderstood the
v1 = t2 - t1
v2 = t3 - t1
part or is the above code doing it a different way?
I could REALLY use some help clearing this up.
Thanks.
[/source]
This topic is closed to new replies.
Advertisement
Popular Topics
Advertisement