- Website design & DirectX code : Riemer Grootjans -
- Rotate your terrain using the keyboard
Using DirectX, it is
very easy to read you keyboard. Simply add a reference to
Microsoft.DirectX.DirectInput and add the following line to
your using block:
using
Microsoft.DirectX.DirectInput;
However, the keyboard
is also called the Device. So, everywhere you used Device to
point to your graphical adapter, you should replace it with
Microsoft.DirectX.Direct3D.Device, 2 times in your whole code.
Also, the DeviceType should be replaced by
Microsoft.DirectX.Direct3D.DeviceType. Try running your
application now, it should give the same result without any
errors.
Now you can make a
connection to your keyboard the same way you connected to your
graphical adapter. First you should create a new variable in
your class :
private
Microsoft.DirectX.DirectInput.Device
keyb;
Then, create a
method InitializeKeyboard :
public void
InitializeKeyboard()
{
keyb = new
Microsoft.DirectX.DirectInput.Device(SystemGuid.Keyboard);
keyb.SetCooperativeLevel(this,
CooperativeLevelFlags.Background |
CooperativeLevelFlags.NonExclusive);
keyb.Acquire();
}
The first line
allocates the system's default keyboard to your variable keyb.
Then you set some flags that adds default keyboard behaviour
to keyb. For example, if your window loses focus, your
keyboard won't be attached to it any longer. Don't forget to
acquire your keyboard and to call this method from your Main
method:
our_directx_form.InitializeKeyboard();
Next we create a
method to read your keyboard:
private void
ReadKeyboard()
{
KeyboardState keys =
keyb.GetCurrentKeyboardState();
if
(keys[Key.Delete])
{
angle+=0.03f;
}
if
(keys[Key.Next])
{
angle-=0.03f;
}
}
Here you put the
keyboard state in a variable 'keys'. With this you can easily
read out the currently pressed keys! Call the ReadKeyboard
method at the end of your OnPaint method, hereby replacing our
old 'angle += 0.05f;' line !
Now the rotation
itself: add a rotation after your translation
:
device.Transform.World =
Matrix.Translation(-HEIGHT/2, -WIDTH/2,
0)*Matrix.RotationZ(angle)
;
Et voila! When you
run the code, you'll see the terrain rotating as you press the
Delete and PageDown buttons!
The final code for
our rotating terrain:
using
System;
using
System.Drawing;
using
System.Collections;
using
System.ComponentModel;
using
System.Windows.Forms;
using
System.Data;
using
Microsoft.DirectX;
using
Microsoft.DirectX.Direct3D;
using
System.IO;
using
Microsoft.DirectX.DirectInput;
namespace
DirectX_Tutorial
{
public class WinForm :
System.Windows.Forms.Form
{
private int WIDTH = 64;
private int HEIGHT = 64;
private
Microsoft.DirectX.Direct3D.Device
device;
private System.ComponentModel.Container components =
null;
private float angle = 0f;
private CustomVertex.PositionColored[]
vertices;
private int[,] heightData;
private int[] indices;
private IndexBuffer ib;
private VertexBuffer vb;
private
Microsoft.DirectX.DirectInput.Device
keyb;
public WinForm()
{
InitializeComponent();
this.SetStyle(ControlStyles.AllPaintingInWmPaint |
ControlStyles.Opaque, true);
}
public void InitializeDevice()
{
PresentParameters presentParams = new
PresentParameters();
presentParams.Windowed = true;
presentParams.SwapEffect =
SwapEffect.Discard;
device = new
Microsoft.DirectX.Direct3D.Device(0,
Microsoft.DirectX.Direct3D.DeviceType.Hardware, this,
CreateFlags.SoftwareVertexProcessing,
presentParams);
device.RenderState.FillMode =
FillMode.WireFrame;
device.RenderState.CullMode =
Cull.None;
}
public void
InitializeKeyboard()
{
keyb = new
Microsoft.DirectX.DirectInput.Device(SystemGuid.Keyboard);
keyb.SetCooperativeLevel(this,
CooperativeLevelFlags.Background |
CooperativeLevelFlags.NonExclusive);
keyb.Acquire();
}
private void CameraPositioning()
{
device.Transform.Projection =
Matrix.PerspectiveFovLH((float)Math.PI/4,
this.Width/this.Height, 1f, 150f);
device.Transform.View = Matrix.LookAtLH(new
Vector3(0,-40,50), new Vector3(0,-5,0), new
Vector3(0,1,0));
device.RenderState.Lighting =
false;
device.RenderState.CullMode =
Cull.None;
}
private void VertexDeclaration()
{
vb = new
VertexBuffer(typeof(CustomVertex.PositionColored),
WIDTH*HEIGHT, device, Usage.Dynamic | Usage.WriteOnly,
CustomVertex.PositionColored.Format,
Pool.Default);
vertices = new
CustomVertex.PositionColored[WIDTH*HEIGHT];
for (int x=0;x<WIDTH;x++)
{
for (int y=0; y<HEIGHT;y++)
{
vertices[x+y*WIDTH].SetPosition(new Vector3(x, y,
heightData[x,y]));
vertices[x+y*WIDTH].Color =
Color.White.ToArgb();
}
}
vb.SetData(vertices, 0
,LockFlags.None);
}
private void IndicesDeclaration()
{
ib = new IndexBuffer(typeof(int),
(WIDTH-1)*(HEIGHT-1)*6, device, Usage.WriteOnly,
Pool.Default);
indices = new
int[(WIDTH-1)*(HEIGHT-1)*6];
for (int x=0;x<WIDTH-1;x++)
{
for (int y=0; y<HEIGHT-1;y++)
{
indices[(x+y*(WIDTH-1))*6] =
(x+1)+(y+1)*WIDTH;
indices[(x+y*(WIDTH-1))*6+1] =
(x+1)+y*WIDTH;
indices[(x+y*(WIDTH-1))*6+2] =
x+y*WIDTH;
indices[(x+y*(WIDTH-1))*6+3] =
(x+1)+(y+1)*WIDTH;
indices[(x+y*(WIDTH-1))*6+4] =
x+y*WIDTH;
indices[(x+y*(WIDTH-1))*6+5] =
x+(y+1)*WIDTH;
}
}
ib.SetData(indices, 0,
LockFlags.None);
}
protected override void
OnPaint(System.Windows.Forms.PaintEventArgs
e)
{
device.Clear(ClearFlags.Target, Color.Black , 1.0f,
0);
device.BeginScene();
device.VertexFormat =
CustomVertex.PositionColored.Format;
device.SetStreamSource(0, vb, 0);
device.Indices = ib;
device.Transform.World =
Matrix.Translation(-HEIGHT/2, -WIDTH/2,
0)*Matrix.RotationZ(angle) ;
device.DrawIndexedPrimitives(PrimitiveType.TriangleList,
0, 0, WIDTH*HEIGHT, 0,
indices.Length/3);
device.EndScene();
device.Present();
this.Invalidate();
ReadKeyboard();
angle+=0.05f;
}
private void
ReadKeyboard()
{
KeyboardState keys =
keyb.GetCurrentKeyboardState();
if (keys[Key.Delete])
{
angle+=0.03f;
}
if (keys[Key.Next])
{
angle-=0.03f;
}
}
private void LoadHeightData()
{
heightData = new
int[WIDTH,HEIGHT];
FileStream fs = new
FileStream("heightdata.raw",FileMode.Open,
FileAccess.Read);
BinaryReader r = new
BinaryReader(fs);
for (int i = 0;i<HEIGHT;i++)
{
for (int y=0; y<WIDTH; y++)
{
int height
=(int)(r.ReadByte()/50);
heightData[WIDTH-1-y,HEIGHT-1-i] =
height;
}
}
r.Close();
}
protected override void Dispose (bool
disposing)
{
if (disposing)
{
if (components != null)
{
components.Dispose();
}
}
base.Dispose(disposing);
}
private void
InitializeComponent()
{
this.components = new
System.ComponentModel.Container();
this.Size = new
System.Drawing.Size(500,500);
this.Text = "DirectX Tutorial";
}
static void Main()
{
using (WinForm our_directx_form = new
WinForm())
{
our_directx_form.LoadHeightData();
our_directx_form.InitializeDevice();
our_directx_form.CameraPositioning();
our_directx_form.VertexDeclaration();
our_directx_form.IndicesDeclaration();
our_directx_form.InitializeKeyboard();
our_directx_form.Show();
Application.Run(our_directx_form);
}
}
}
}
|