/////////////////////////////////////////////
// GameWindow_Sample04.cpp
// Copyrignt (c) 2024 byYsama
/////////////////////////////////////////////
using System;
using OpenTK;						//OpenTKを使用する際に必須
using OpenTK.Graphics;				//OpenTKのグラフィックを使用する際に必須
using OpenTK.Graphics.OpenGL;		//OpenGLを使用する際に必要
using OpenTK.Input;					//OpenTKで入力を行う際に必要（例：Keyboiard）
using OpenTK_Primitives;			//OpenTK自作図形ライブラリー

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

	class gWindow : GameWindow	//GameWindowクラスからユーザーウィンドウを派生させる
	{
		OTKPrims pv = new OTKPrims();					//otkPrimitivesクラスインスタンス
		float Theta_Sun;								//太陽の自転角
		float Theta_Earth;								//地球の自転角
		float Theta_Moon;								//月の自転角
		bool SorW = true;								//Solidか、Wireかのフラグ
		bool drawStop = false;							//描画停止

		public gWindow() : base(640, 480, GraphicsMode.Default, "OpenTK GameWindow")	//既定引数
		{
			//Mouse割込み
			this.MouseDown += gW_MouseDown;
			this.MouseMove += gW_MouseMove;
			//Key割込み
			this.KeyUp += gW_KeyUp;
			this.KeyDown += gW_KeyDown;
			this.KeyPress += gW_KeyPress;
		}

		//ウィンドウの起動時に実行される
		protected override void OnLoad(EventArgs e)
		{
			base.OnLoad(e);								//既定処理
			GL.ClearColor(Color4.Black);				//画面消去色の設定
			GL.Enable(EnableCap.DepthTest);				//深度チェックを有効化する
			GL.Enable(EnableCap.Normalize);				//法線の正規化を有効にする
			//光源の使用
			GL.Enable(EnableCap.Lighting);
			//ライト0の設定
			GL.Enable(EnableCap.Light0);
			float[] pos0 = new float[] {50.0f, 50.0f, 50.0f, 1.0f };
			GL.Light(LightName.Light0, LightParameter.Position, pos0);
			//ライト1の設定
			GL.Enable(EnableCap.Light1);
			float[] pos1 = new float[] {0.0f, -50.0f, 0.0f, 1.0f };
			GL.Light(LightName.Light1, LightParameter.Position, pos1);
			//ライト2の設定
			GL.Enable(EnableCap.Light2);
			float[] pos2 = new float[] {100.0f, 100.0f, 100.0f, 1.0f };
			GL.Light(LightName.Light2, LightParameter.Position, pos2);
		}

		//ウィンドウのサイズが変更された場合に実行される
		protected override void OnResize(EventArgs e)
		{
			base.OnResize(e);							//既定処理
			//ビューポートの設定
			GL.Viewport(ClientRectangle.X, ClientRectangle.Y, ClientRectangle.Width, ClientRectangle.Height);
			//視体積の設定
			GL.MatrixMode(MatrixMode.Projection);
			Matrix4 projection = Matrix4.CreatePerspectiveFieldOfView((float)Math.PI / 4, (float)Width / (float)Height, 50.0f, 10000.0f);	//glPerspective(fov, aspect, near, far);
			GL.LoadMatrix(ref projection);
		}

		//ウィンドウイベントが更新された場合に実行される（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);						//既定処理
			if(drawStop)
				return;									//描画停止
			GL.Clear(ClearBufferMask.ColorBufferBit | ClearBufferMask.DepthBufferBit);
			GL.MatrixMode(MatrixMode.Modelview);		//モデルビューモードを選択
			//視点を設定して原点(0, 0, 0)を見る
			Vector3 eye = new Vector3(0.0f, 200.0f, 60.0f);
			Matrix4 modelview = Matrix4.LookAt(eye, Vector3.Zero, Vector3.UnitY);	//gluLookAt(0.0, 100.0, 20.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0);
			GL.LoadMatrix(ref modelview);				//現在の変換マトリックスに設定
			//以下に描画処理を行う
			//鏡面光成分のセット
			//float[] material_specular = new float[4] {0.2f, 0.2f, 0.2f, 1.0f};		//鏡面光成分
			GL.Material(MaterialFace.Front, MaterialParameter.Specular, Color4.White);
			GL.Material(MaterialFace.Front, MaterialParameter.Shininess, 32.0f);
			GL.Material(MaterialFace.Front, MaterialParameter.Diffuse, Color4.OrangeRed);
			pv.Sphere(SorW,20.0);						//太陽/
			GL.PushMatrix();
			{
				GL.Rotate(Theta_Sun, 0.0f, 0.0f, 1.0f);	//z軸周りにTheta_Sun度回転
				GL.Translate(60.0f, 0.0f, 0.0f);		//x軸に60平行移動
				GL.Rotate(Theta_Earth, 0.0f, 0.0f, 1.0f);//z軸周りにTheta_Earth度回転
				GL.Material(MaterialFace.Front, MaterialParameter.Diffuse, Color4.SeaGreen);
				pv.Sphere(SorW, 10.0);					//地球
				GL.Rotate(Theta_Moon, 0.0f, 0.0f, 1.0f);//z軸周りにTheta_Moon度回転
				GL.Translate(20.0f, 0.0f, 0.0f);		//x軸に20平行移動
				GL.Material(MaterialFace.Front, MaterialParameter.Diffuse, Color4.Yellow);
				pv.Sphere(SorW, 5.0);					//月
			}
			GL.PopMatrix();
			Theta_Sun += 2.0f;
			Theta_Earth -= 10.0f;
			Theta_Moon += 6.0f;
			//ダブルバッファー
			this.SwapBuffers();
		}

		//Mouse割込み
		private void gW_MouseDown(object sender, MouseButtonEventArgs e)
		{
			if(e.Button == MouseButton.Left)
				SorW = !SorW;
			else if(e.Button == MouseButton.Right)
				drawStop = !drawStop;
		}

		private void gW_MouseMove(object sender, MouseMoveEventArgs e)
		{
		}

		//Key割込み
		private void gW_KeyUp(object sender, KeyboardKeyEventArgs e)
		{
		}

		private void gW_KeyDown(object sender, KeyboardKeyEventArgs e)
		{
		}

		private void gW_KeyPress(object sender, KeyPressEventArgs e)
		{
		}
	}
}
