///////////////////////////////////////////
// GLControl_Base.cpp
// OpenTKをGLControlで使う場合のスケルトン
// Copyrignt (c) 2024 byYsama
///////////////////////////////////////////
using System;
using System.Drawing;
using System.Windows.Forms;
using OpenTK;						//OpenTKを使用する際に必須
using OpenTK.Graphics;				//OpenTKのグラフィックを使用する際に必須
using OpenTK.Graphics.OpenGL;		//OpenGLを使用する際に必要
//using OpenTK.Input;					//OpenTKで入力を行う際に必要（例：Keyboiard）－マウスを使う場合Formsのマウスイベントと干渉するので注意

namespace GLControl_Base
{
	//アプリケーションクラス
	public class App
	{
		[STAThread]
		public static void Main()
		{
			Application.Run(new MainForm());
		}
	}

	public class MainForm : Form
	{
		private GLControl glControl;	//GLControlへのポインター

		public MainForm()
		{
			this.Text = "OpenTK_GLControl_Base";
			this.ClientSize = new Size(640, 480);
			this.MinimumSize = new Size(480, 360);
			this.Load += new EventHandler(Form_Load);
		}

		private void Form_Load(object sender, EventArgs e)
		{
			//Formのコントロールレイアウトロジック保留
			SuspendLayout();
			//GLControl関連
			glControl = new GLControl();
			glControl.Size = new Size(this.ClientSize.Width, this.ClientSize.Height);
			glControl.Location = new Point(0, 0);
			glControl.Load += new EventHandler(glControl_Load);
			glControl.Resize += new EventHandler(glControl_Resize);
			glControl.Paint += new PaintEventHandler(glControl_Paint);
			//glControl.MouseDown += glc_MouseDown;
			//glControl.MouseMove += glc_MouseMove;
			//glControl.MouseUp += glc_MouseUp;
			Controls.Add(glControl);
			//Formのコントロールレイアウトロジック再開
			ResumeLayout();
		}
/*
		private void glc_MouseDown(object sender, MouseEventArgs e)
		{
		}
*/
/*
		private void glc_MouseMove(object sender, MouseEventArgs e)
		{
		}
*/
/*
		private void glc_MouseUp(object sender, MouseEventArgs e)
		{
		}
*/
		private void glControl_Load(object sender, EventArgs e)
		{
			GL.ClearColor(glControl.BackColor);	//画面消去色の設定
			GL.Enable(EnableCap.DepthTest);		//深度バッファの使用
		}

		private void glControl_Resize(object sender, EventArgs e)
		{
			glControl.Dock = DockStyle.Fill;	//All the control's edges are docked to the all edges of its containing control and sized appropriately.
			glControl_SetProjection();
			glControl_SetModelView();			//ModelViewの設定
			//glControl_SetLight();				//ライトの設定
			glControl.Refresh();				//再描画
		}

		private void glControl_Paint(object sender, PaintEventArgs e)
		{
			//色と深度バッファーを初期化
			GL.Clear(ClearBufferMask.ColorBufferBit | ClearBufferMask.DepthBufferBit);
			//モデルビューにして視点を設定
			glControl_SetModelView();
			//以下に描画処理を行う
			GL.Begin(PrimitiveType.Quads);
				GL.Color4(Color4.White);							//色名で持定
				GL.Vertex3(-1.0f, 1.0f, 0.0f);
				GL.Color4(new float[] { 1.0f, 0.0f, 0.0f, 1.0f });	//配列で特定
				GL.Vertex3(-1.0f, -1.0f, 0.0f);
				GL.Color4(0.0f, 1.0f, 0.0f, 1.0f);					//4つの引数にfloat型で特定
				GL.Vertex3(1.0f, -1.0f, 0.0f);
				GL.Color4((byte)0, (byte)0, (byte)255, (byte)255);  //byte型で特定
				GL.Vertex3(1.0f, 1.0f, 0.0f);
			GL.End();
			//バッファー変換
			glControl.SwapBuffers();
		}

		private void glControl_SetProjection()
		{
			//ビューポートの設定
			GL.Viewport(0, 0, glControl.Size.Width, glControl.Size.Height);
			//視野空間の設定
			GL.MatrixMode(MatrixMode.Projection);
			//透視投影－尚、glControl.AspectRatioは、(float)glControl.Width / (float)glControl.Heightと等価
			Matrix4 projection = Matrix4.CreatePerspectiveFieldOfView((float)Math.PI / 4, glControl.AspectRatio, 0.1f, 64.0f);
			GL.LoadMatrix(ref projection);
		}

		void glControl_SetModelView(float x = 0.0f, float y = 0.0f, float z = 5.0f)
		{
			GL.MatrixMode(MatrixMode.Modelview);	//モデルビューを選択
			//視点を設定して原点(0, 0, 0)を見る
			Vector3 eye = new Vector3(x, y, z);
			Matrix4 modelview = Matrix4.LookAt(eye, Vector3.Zero, Vector3.UnitY);	//gluLookAt(0, 0, 5, 0, 0, 0, 0, 1, 0);
			GL.LoadMatrix(ref modelview);			//現在の変換マトリックスに設定
		}

		void glControl_SetLight(float x = 50.0f, float y = 50.0f, float z = 10.0f)
		{
			//光源の使用
			GL.Enable(EnableCap.Lighting);
			//ライト0の設定
			GL.Enable(EnableCap.Light0);
			float[] pos = new float[] {x, y, z, 0.0f };
			GL.Light(LightName.Light0, LightParameter.Position, pos);
		}
	}
}
