Tutorial 4, DirectX using C#

DirectX using C#

Tutorial 4

Refresh event

When you will resize the form, the output distorts away. This is because the Transform projection we set for our camera isn't effective with the new size of form.

Solution

Reset tranform projection everytime, form is resized


form.Resize += new EventHandler(form_Resize);

void form_Resize(object sender, EventArgs e)
            {
                SunLightColor = Color.White;
                AspectRatio = (float)form.Width / (float)form.Height;
                this.device.Transform.Projection = Matrix.PerspectiveFovLH(FieldOfView, AspectRatio, 0.3f, 500f);
            }

Output

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();
            form.Resize += new EventHandler(form_Resize);

        }

            void form_Resize(object sender, EventArgs e)
            {
                SunLightColor = Color.White;
                AspectRatio = (float)form.Width / (float)form.Height;
                this.device.Transform.Projection = Matrix.PerspectiveFovLH(FieldOfView, AspectRatio, 0.3f, 500f);
            }
        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();
            //this.Size = new Size(800, 800);
            SetStyle(ControlStyles.AllPaintingInWmPaint | ControlStyles.Opaque, true);
            X = new cosmicX(this);
            truck = new cosmicX.Object("slam\\slam.x", 1);
            X.Stare(truck, 10, 4);
            Resize += new EventHandler(Form1_Resize);
        }

        void Form1_Resize(object sender, EventArgs e)
        {
            X.Stare(truck, 10, 4);
        }
        protected override void OnPaint(PaintEventArgs e)
        {
            base.OnPaint(e);
            X.RenderX();
        }
    }
}

Comments

Popular Posts