/////////////////////////////////////////////
// GameWindow_Base.cpp
// OpenTKをGameWindowで使う場合のスケルトン
// Copyrignt (c) 2024 byYsama
/////////////////////////////////////////////
using System;
using OpenTK;						//OpenTKを使用する際に必須
using OpenTK.Graphics;				//OpenTKのグラフィックを使用する際に必須
using OpenTK.Graphics.OpenGL;		//OpenGLを使用する際に必要
using OpenTK.Input;					//OpenTKで入力を行う際に必要（例：Keyboiard）

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

	class gWindow : GameWindow	//GameWindowクラスからユーザーウィンドウを派生させる
	{
		public gWindow() : base(640, 480, GraphicsMode.Default, "OpenTK GameWindow")	//既定引数
		{
		}

		//ウィンドウの起動時に実行される
		protected override void OnLoad(EventArgs e)
		{
			base.OnLoad(e);								//既定処理
			GL.ClearColor(Color4.Black);				//画面消去色の設定
			GL.Enable(EnableCap.DepthTest);				//深度チェックを有効化する
		}

		//ウィンドウのサイズが変更された場合に実行される
		protected override void OnResize(EventArgs e)
		{
			base.OnResize(e);							//既定処理
			//ビューポートの設定
			GL.Viewport(0, 0, ClientRectangle.Width, ClientRectangle.Height);
			//視野空間の設定
			SetProjection();
		}

		//ウィンドウイベントが更新された場合に実行される（OnRenderFrameの前に実行される）
		protected override void OnUpdateFrame(FrameEventArgs e)
		{
			base.OnUpdateFrame(e);
			//ESCキーが押されたら終了
			if(Keyboard.GetState().IsKeyDown(Key.Escape))
			{
				Exit();
			}
		}

		//ウィンドウ描画が更新された場合に実行される
		protected override void OnRenderFrame(FrameEventArgs e)
		{
			base.OnRenderFrame(e);						//既定処理
			GL.Clear(ClearBufferMask.ColorBufferBit | ClearBufferMask.DepthBufferBit);
			SetModelView();								//モデルビューモードで視点を設定して原点(0, 0, 0)を見る
			//以下に描画処理を行う
			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();
			//バッファー変換
			SwapBuffers();
		}

		private void SetProjection()
		{
			//視野空間の設定
			GL.MatrixMode(MatrixMode.Projection);
			//透視投影
			Matrix4 projection = Matrix4.CreatePerspectiveFieldOfView((float)Math.PI / 4, (float)Width / (float)Height, 0.1f, 64.0f);	//glPerspective(fov, aspect, near, far);
			GL.LoadMatrix(ref projection);
		}

		void 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 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);
		}
	}
}
