Tutorial 3
DirectX using C#
Tutorial 3
Camera Setup
this.device.Transform.Projection = Matrix.PerspectiveFovLH(FieldOfView, AspectRatio, 0.3f, 500f);
- Field Of View - Angle in radians
- AspectRatio - ratio of width to height
- zNearPlane - Near point
- zFarPlane - Far point
this.device.Transform.View = Matrix.LookAtLH(CameraPosition, LookAt, UP);
- CameraPosition - Vector3 for position
- LookAt - point where it is staring
- UP - direction vector to decide camera orientation [direction of the yellow Triangle arrow, see fig.]
Local Axis of Object
Local Vs Global system
Suppose you want to move a car model forward, then you must advance its position in the direction of your car or local z-axis of the car. Now, every time you want to move the car, you have to add the position vector with a vector in direction of local axis to get new position vector. This can be only done if you can know the global equivalent of the local axis.
LocalToGlobal()
Object.orientation is a Vector3 and to understand it, see this code chunk under Object.Render()CosmicX.device.Transform.World = Matrix.Scaling(Scaling.X, Scaling.Y, Scaling.Z) * Matrix.RotationX(Orientation.X) * Matrix.RotationZ(Orientation.Z) * Matrix.RotationY(Orientation.Y) * Matrix.Translation(Position);
Function Vector3 Object.LocalToGlobal() actually rotates the local axis of object wrt its orientation to get desired Global axis.
Staring an object
public void Stare(Object o, float distance, float height) { CameraPosition = LookAt = o.Position; LookAt.Y += 1; Vector3 v = o.LocalToGlobal(); v.Multiply(distance / v.Length()); CameraPosition += v; CameraPosition.Y = o.Position.Y + height; this.device.Transform.View = Matrix.LookAtLH(CameraPosition, LookAt, UP); }
Lightening
Two category of lights is featured by DirectX
- Ambient light - present everywhere, low intense, non-directional
- Direct light - directional, varying intensity
public Color SunLightColor //Ambient light { get { return Device.RenderState.Ambient; } set { Device.RenderState.Ambient = value; } }
Direct light
this.device.Lights[0].Type = LightType.Directional; this.device.Lights[0].Diffuse = Color.White; this.device.Lights[0].Direction = new Vector3(1, 1, -1);
Complete code
using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Text; using System.Windows.Forms; using Microsoft.DirectX; using Microsoft.DirectX.Direct3D; using D3D = Microsoft.DirectX.Direct3D; namespace XBasic { public partial class Form1 : Form { class cosmicX { event EventHandler Render; #region -FIELDS- D3D.Device device; Form form; float _AspectRatio, _FieldOfView; static cosmicX _CosmicX; Vector3 CameraPosition, LookAt; Vector3 UP = new Vector3(0, 1, 0); #endregion #region -Properties- public D3D.Device Device { get { return device; } set { device = value; } } public static cosmicX CosmicX { get { return cosmicX._CosmicX; } set { cosmicX._CosmicX = value; } } public float FieldOfView { get { return _FieldOfView; } set { _FieldOfView = value; } } public float AspectRatio { get { return _AspectRatio; } set { _AspectRatio = value; } } public Color SunLightColor { get { return Device.RenderState.Ambient; } set { Device.RenderState.Ambient = value; } } #endregion #region -Methods- public cosmicX(Form f) { CosmicX = this; this.form = f; D3D.PresentParameters presentParams = new D3D.PresentParameters(); presentParams.Windowed = true; presentParams.SwapEffect = SwapEffect.Discard; presentParams.AutoDepthStencilFormat = DepthFormat.D16; presentParams.EnableAutoDepthStencil = true; this.Device = new D3D.Device(0, D3D.DeviceType.Hardware, f, CreateFlags.SoftwareVertexProcessing, presentParams); SetUp(); } void SetUp() { this.device.RenderState.Lighting = true; this.device.Lights[0].Type = LightType.Directional; this.device.Lights[0].Diffuse = Color.White; this.device.Lights[0].Direction = new Vector3(1, 1, -1); this.device.Lights[0].Update(); this.device.Lights[0].Enabled = true; this.device.Lights[1].Type = LightType.Directional; this.device.Lights[1].Diffuse = Color.White; this.device.Lights[1].Direction = new Vector3(-1, -1, -1); this.device.Lights[1].Update(); this.device.Lights[1].Enabled = true; SunLightColor = Color.White; FieldOfView = 3.14f / 4; AspectRatio = (float)form.Width / (float)form.Height; this.device.Transform.Projection = Matrix.PerspectiveFovLH(FieldOfView, AspectRatio,0.3f, 500f); } public void RenderX() { this.device.Clear(ClearFlags.Target | ClearFlags.ZBuffer, Color.DarkSlateBlue, 1.0f, 0); this.device.BeginScene(); if (Render != null) Render(this, null); this.device.EndScene(); this.device.Present(); this.form.Invalidate(); } public void Stare(Object o, float distance, float height) { CameraPosition = LookAt = o.Position; LookAt.Y += 1; Vector3 v = o.LocalToGlobal(); v.Multiply(distance / v.Length()); CameraPosition += v; CameraPosition.Y = o.Position.Y + height; this.device.Transform.View = Matrix.LookAtLH(CameraPosition, LookAt, UP); } #endregion public class Object { private Mesh mesh; private Material[] materials; private Texture[] textures; object _Tag; public object Tag { get { return _Tag; } set { _Tag = value; } } private float radius; public Vector3 Position, centre, Orientation, LocalAxis, Scaling; public Object(string Filename, float scaling) : this(Filename, scaling, true) { } public Object(string Filename, float scaling, bool renderable) { Scaling = new Vector3(scaling, scaling, scaling); LoadMesh(Filename, ref mesh, ref materials, ref textures, ref radius, scaling, out centre); Position = new Vector3(0, 0, 0); if (renderable) CosmicX.Render += new EventHandler(_CosmicX_Render); Orientation = new Vector3(0, 0, 0); LocalAxis = new Vector3(0, 0, 1); } public void LoadMesh(string filename, ref Mesh mesh, ref Material[] meshmaterials, ref Texture[] meshtextures, ref float meshradius, float scaling, out Vector3 meshcenter) { if (!System.IO.File.Exists(filename)) { throw new Exception("File not found " + filename); } ExtendedMaterial[] materialarray; mesh = Mesh.FromFile(filename, MeshFlags.Managed, CosmicX.device, out materialarray); if ((materialarray != null) && (materialarray.Length > 0)) { meshmaterials = new Material[materialarray.Length]; meshtextures = new Texture[materialarray.Length]; for (int i = 0; i < materialarray.Length; i++) { meshmaterials[i] = materialarray[i].Material3D; meshmaterials[i].Ambient = meshmaterials[i].Diffuse; if ((materialarray[i].TextureFilename != null) && (materialarray[i].TextureFilename != string.Empty)) { System.IO.FileInfo fi = new System.IO.FileInfo(filename); if (System.IO.File.Exists(fi.DirectoryName + "\\" + materialarray[i].TextureFilename)) { meshtextures[i] = TextureLoader.FromFile(CosmicX.device, fi.DirectoryName + "\\" + materialarray[i].TextureFilename); } else System.Diagnostics.Debug.Print("File not found: " + materialarray[i].TextureFilename + " !"); } } } mesh = mesh.Clone(mesh.Options.Value, CustomVertex.PositionNormalTextured.Format, CosmicX.device); mesh.ComputeNormals(); VertexBuffer vertices = mesh.VertexBuffer; GraphicsStream stream = vertices.Lock(0, 0, LockFlags.None); meshradius = Geometry.ComputeBoundingSphere(stream, mesh.NumberVertices, mesh.VertexFormat, out meshcenter) * scaling; } public Vector3 LocalToGlobal() { Vector4 v = Vector3.Transform(LocalAxis, Matrix.RotationY(Orientation.Y) * Matrix.RotationX(Orientation.X) * Matrix.RotationZ(Orientation.Z)); return new Vector3(v.X, v.Y, v.Z); } public void DrawMesh() { for (int i = 0; i < materials.Length; i++) { CosmicX.device.Material = materials[i]; CosmicX.device.SetTexture(0, textures[i]); mesh.DrawSubset(i); } } void _CosmicX_Render(object sender, EventArgs e) { Render(); } public void Render() { CosmicX.device.Transform.World = Matrix.Scaling(Scaling.X, Scaling.Y, Scaling.Z) * Matrix.RotationX(Orientation.X) * Matrix.RotationZ(Orientation.Z) * Matrix.RotationY(Orientation.Y) * Matrix.Translation(Position); DrawMesh(); } public void Dispose() { CosmicX.Render -= _CosmicX_Render; mesh = null; materials = null; textures = null; System.GC.SuppressFinalize(this); } } } cosmicX X; cosmicX.Object truck; public Form1() { InitializeComponent(); SetStyle(ControlStyles.AllPaintingInWmPaint | ControlStyles.Opaque, true); X = new cosmicX(this); truck = new cosmicX.Object("slam\\slam.x", 1); X.Stare(truck, 10, 5); } protected override void OnPaint(PaintEventArgs e) { base.OnPaint(e); X.RenderX(); } } }
Comments
Post a Comment