using System;
using System.Drawing;
using System.ComponentModel;
using System.Windows.Forms;
using Microsoft.DirectX;
using Microsoft.DirectX.Direct3D;
using Direct3D = Microsoft.DirectX.Direct3D;
using Microsoft.DirectX.DirectInput;
using DirectInput = Microsoft.DirectX.DirectInput;

namespace D3DProject01
{
    public partial class Form1 : Form
    {
        Microsoft.DirectX.Direct3D.Device device = null;
        Microsoft.DirectX.DirectInput.Device inputDevice = null;
        VertexBuffer[] vertexBuffers = new VertexBuffer[6];
        Texture[] textures;
        KeyboardState keyState;
        int startTime;
        float posX = 0.0f;
       
        public Form1()
        {
        }

        public bool CreateDevice()//デバイスの生成
        {
            try
            {
                PresentParameters presentParams = new PresentParameters();
                presentParams.Windowed = true;
                presentParams.SwapEffect = SwapEffect.Discard;
                device = new Direct3D.Device(0, Direct3D.DeviceType.Hardware, this, CreateFlags.SoftwareVertexProcessing, presentParams);

                device.RenderState.Lighting = false;

                inputDevice = new DirectInput.Device(SystemGuid.Keyboard);
                inputDevice.Acquire();

                startTime = System.Environment.TickCount;

                return true;
            }
            catch (DirectXException)
            {
                return false;
            }
        }

        private void CreateModel()//図形の作成
        {
            CustomVertex.PositionColoredTextured[] verts;
            vertexBuffers[0] = new VertexBuffer(typeof(CustomVertex.PositionColoredTextured), 4, device, 0, CustomVertex.PositionColoredTextured.Format, Pool.Default);
            verts = (CustomVertex.PositionColoredTextured[])vertexBuffers[0].Lock(0, 0);
            verts[0].X = -1.0f; verts[0].Y = -1.0f; verts[0].Z = -1.0f; verts[0].Color = System.Drawing.Color.White.ToArgb();
            verts[0].Tu = 0.0f; verts[0].Tv = 1.0f;
            verts[1].X = -1.0f; verts[1].Y = 1.0f; verts[1].Z = -1.0f; verts[1].Color = System.Drawing.Color.White.ToArgb();
            verts[1].Tu = 0.0f; verts[1].Tv = 0.0f;
            verts[2].X = 1.0f; verts[2].Y = -1.0f; verts[2].Z = -1.0f; verts[2].Color = System.Drawing.Color.White.ToArgb();
            verts[2].Tu = 1.0f; verts[2].Tv = 1.0f;
            verts[3].X = 1.0f; verts[3].Y = 1.0f; verts[3].Z = -1.0f; verts[3].Color = System.Drawing.Color.White.ToArgb();
            verts[3].Tu = 1.0f; verts[3].Tv = 0.0f;
            vertexBuffers[0].Unlock();
 
            vertexBuffers[1] = new VertexBuffer(typeof(CustomVertex.PositionColoredTextured), 4, device, 0, CustomVertex.PositionColoredTextured.Format, Pool.Default);
            verts = (CustomVertex.PositionColoredTextured[])vertexBuffers[1].Lock(0, 0);
            verts[0].X = 1.0f; verts[0].Y = -1.0f; verts[0].Z = -1.0f; verts[0].Color = System.Drawing.Color.White.ToArgb();
            verts[0].Tu = 0.0f; verts[0].Tv = 1.0f;
            verts[1].X = 1.0f; verts[1].Y = 1.0f; verts[1].Z = -1.0f; verts[1].Color = System.Drawing.Color.White.ToArgb();
            verts[1].Tu = 0.0f; verts[1].Tv = 0.0f;
            verts[2].X = 1.0f; verts[2].Y = -1.0f; verts[2].Z = 1.0f; verts[2].Color = System.Drawing.Color.White.ToArgb();
            verts[2].Tu = 1.0f; verts[2].Tv = 1.0f;
            verts[3].X = 1.0f; verts[3].Y = 1.0f; verts[3].Z = 1.0f; verts[3].Color = System.Drawing.Color.White.ToArgb();
            verts[3].Tu = 1.0f; verts[3].Tv = 0.0f;
            vertexBuffers[1].Unlock();

            vertexBuffers[2] = new VertexBuffer(typeof(CustomVertex.PositionColoredTextured), 4, device, 0, CustomVertex.PositionColoredTextured.Format, Pool.Default);
            verts = (CustomVertex.PositionColoredTextured[])vertexBuffers[2].Lock(0, 0);
            verts[0].X =  1.0f; verts[0].Y = -1.0f; verts[0].Z = 1.0f; verts[0].Color = System.Drawing.Color.White.ToArgb();
            verts[0].Tu = 0.0f; verts[0].Tv = 1.0f;
            verts[1].X =  1.0f; verts[1].Y = 1.0f; verts[1].Z = 1.0f; verts[1].Color = System.Drawing.Color.White.ToArgb();
            verts[1].Tu = 0.0f; verts[1].Tv = 0.0f;
            verts[2].X = -1.0f; verts[2].Y = -1.0f; verts[2].Z = 1.0f; verts[2].Color = System.Drawing.Color.White.ToArgb();
            verts[2].Tu = 1.0f; verts[2].Tv = 1.0f;
            verts[3].X = -1.0f; verts[3].Y = 1.0f; verts[3].Z = 1.0f; verts[3].Color = System.Drawing.Color.White.ToArgb();
            verts[3].Tu = 1.0f; verts[3].Tv = 0.0f;
            vertexBuffers[2].Unlock();

            vertexBuffers[3] = new VertexBuffer(typeof(CustomVertex.PositionColoredTextured), 4, device, 0, CustomVertex.PositionColoredTextured.Format, Pool.Default);
            verts = (CustomVertex.PositionColoredTextured[])vertexBuffers[3].Lock(0, 0);
            verts[0].X = -1.0f; verts[0].Y = -1.0f; verts[0].Z = 1.0f; verts[0].Color = System.Drawing.Color.White.ToArgb();
            verts[0].Tu = 0.0f; verts[0].Tv = 1.0f;
            verts[1].X = -1.0f; verts[1].Y = 1.0f; verts[1].Z = 1.0f; verts[1].Color = System.Drawing.Color.White.ToArgb();
            verts[1].Tu = 0.0f; verts[1].Tv = 0.0f;
            verts[2].X = -1.0f; verts[2].Y = -1.0f; verts[2].Z = -1.0f; verts[2].Color = System.Drawing.Color.White.ToArgb();
            verts[2].Tu = 1.0f; verts[2].Tv = 1.0f;
            verts[3].X = -1.0f; verts[3].Y = 1.0f; verts[3].Z = -1.0f; verts[3].Color = System.Drawing.Color.White.ToArgb();
            verts[3].Tu = 1.0f; verts[3].Tv = 0.0f;
            vertexBuffers[3].Unlock();

            vertexBuffers[4] = new VertexBuffer(typeof(CustomVertex.PositionColoredTextured), 4, device, 0, CustomVertex.PositionColoredTextured.Format, Pool.Default);
            verts = (CustomVertex.PositionColoredTextured[])vertexBuffers[4].Lock(0, 0);
            verts[0].X = -1.0f; verts[0].Y = 1.0f; verts[0].Z = -1.0f; verts[0].Color = System.Drawing.Color.White.ToArgb();
            verts[0].Tu = 0.0f; verts[0].Tv = 1.0f;
            verts[1].X = -1.0f; verts[1].Y = 1.0f; verts[1].Z = 1.0f; verts[1].Color = System.Drawing.Color.White.ToArgb();
            verts[1].Tu = 0.0f; verts[1].Tv = 0.0f;
            verts[2].X = 1.0f; verts[2].Y = 1.0f; verts[2].Z = -1.0f; verts[2].Color = System.Drawing.Color.White.ToArgb();
            verts[2].Tu = 1.0f; verts[2].Tv = 1.0f;
            verts[3].X = 1.0f; verts[3].Y = 1.0f; verts[3].Z = 1.0f; verts[3].Color = System.Drawing.Color.White.ToArgb();
            verts[3].Tu = 1.0f; verts[3].Tv = 0.0f;
            vertexBuffers[4].Unlock();

            vertexBuffers[5] = new VertexBuffer(typeof(CustomVertex.PositionColoredTextured), 4, device, 0, CustomVertex.PositionColoredTextured.Format, Pool.Default);
            verts = (CustomVertex.PositionColoredTextured[])vertexBuffers[5].Lock(0, 0);
            verts[0].X = -1.0f; verts[0].Y = -1.0f; verts[0].Z =1.0f; verts[0].Color = System.Drawing.Color.White.ToArgb();
            verts[0].Tu = 0.0f; verts[0].Tv = 1.0f;
            verts[1].X = -1.0f; verts[1].Y = -1.0f; verts[1].Z = -1.0f; verts[1].Color = System.Drawing.Color.White.ToArgb();
            verts[1].Tu = 0.0f; verts[1].Tv = 0.0f;
            verts[2].X = 1.0f; verts[2].Y = -1.0f; verts[2].Z = 1.0f; verts[2].Color = System.Drawing.Color.White.ToArgb();
            verts[2].Tu = 1.0f; verts[2].Tv = 1.0f;
            verts[3].X = 1.0f; verts[3].Y = -1.0f; verts[3].Z = -1.0f; verts[3].Color = System.Drawing.Color.White.ToArgb();
            verts[3].Tu = 1.0f; verts[3].Tv = 0.0f;
            vertexBuffers[5].Unlock();

            textures = new Texture[6];
            textures[0] = TextureLoader.FromFile(device, Application.StartupPath + @"\..\..\sample0.bmp");
            textures[1] = TextureLoader.FromFile(device, Application.StartupPath + @"\..\..\sample1.bmp");
            textures[2] = TextureLoader.FromFile(device, Application.StartupPath + @"\..\..\sample2.bmp");
            textures[3] = TextureLoader.FromFile(device, Application.StartupPath + @"\..\..\sample3.bmp");
            textures[4] = TextureLoader.FromFile(device, Application.StartupPath + @"\..\..\sample4.bmp");
            textures[5] = TextureLoader.FromFile(device, Application.StartupPath + @"\..\..\sample5.bmp");

        }

        private void SetProjection()//カメラの視野角設定
        {
            device.Transform.Projection = Matrix.PerspectiveFovLH((float)Math.PI / 4, 1.0f, 1.0f, 100.0f);
        }

        private void SetCamera()//カメラの位置設定
        {
            device.Transform.View = Matrix.LookAtLH(new Vector3(0.0f, 0.0f, -5.0f), new Vector3(0.0f, 0.0f, 0.0f), new Vector3(0.0f, 1.0f, 0.0f));
        }

        private void SetLocation()//図形の位置設定
        {
            int currentTime = System.Environment.TickCount;
            int diffTime = currentTime - startTime;
            float rot = (float)diffTime / 10000.0f * (float) Math.PI * 2.0f;
            
            Matrix rotate1 = Matrix.RotationY(rot);
            Matrix rotate2 = Matrix.RotationX(rot);
            Matrix rotate = Matrix.Multiply(rotate1, rotate2);

            keyState = inputDevice.GetCurrentKeyboardState();
            
            if (keyState[DirectInput.Key.Left])
            {
                posX = posX - 0.1f;
            }
            if (keyState[DirectInput.Key.Right])
            {
                posX = posX + 0.1f;
            }

            Matrix trans = Matrix.Translation(posX, 0.0f, 0.0f);

            device.Transform.World = Matrix.Multiply(rotate, trans);

        }

        private void Draw()//図形の描画
        {
            if (device == null) return;

            
            device.Clear(ClearFlags.Target, System.Drawing.Color.Black, 1.0f, 0);
            device.BeginScene();

            device.TextureState[0].ColorOperation = TextureOperation.Modulate;
            device.TextureState[0].ColorArgument1 = TextureArgument.TextureColor;
            device.TextureState[0].ColorArgument2 = TextureArgument.Current;
            device.TextureState[0].AlphaOperation = TextureOperation.Disable; 

            for(int i=0; i<6; i++){

                device.SetTexture(0, textures[i]);
                device.SetStreamSource(0, vertexBuffers[i], 0);
                device.VertexFormat = CustomVertex.PositionColoredTextured.Format;
                device.DrawPrimitives(PrimitiveType.TriangleStrip, 0, 2);
            }

            device.EndScene();
            device.Present();
        }

        static void Main()//メイン関数
        {
            using (Form1 frm = new Form1())
            {
                if (!frm.CreateDevice()) 
                {
                    MessageBox.Show("Error : CreateDevice");
                    return;
                }

                frm.Show();//Form1の表示開始
                frm.CreateModel();

                while (frm.Created)//描画処理ループ
                {
                    frm.SetProjection();
                    frm.SetCamera();
                    frm.SetLocation();
                    frm.Draw();
                    Application.DoEvents();
                }
            }
        }

    }
}