cscの作法 その368

# 概要
cscの作法、調べてみた。
opentkのgamewindow使ってみた。
練習問題、やってみた。

# 練習問題
キーでカメラを動かせ。

# 参考にしたページ。

https://github.com/MaaikeG/Rasterizer

# 写真

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/18104/d5921daa-e749-df89-bd58-c35114dc4357.png)

# サンプルコード

```

using System;
using System.Drawing;
using OpenTK;
using OpenTK.Graphics;
using OpenTK.Graphics.OpenGL;
using OpenTK.Input;

namespace App
{
	public class Camera {
		public Vector3 position = Vector3.Zero;
		public Vector3 orientation = new Vector3((float) Math.PI, 0f, 0f);
		public float moveSpeed = 0.2f;
		public float sensitivity = 0.01f;
		public Matrix4 GetViewMatrix() {
			Vector3 lookat = new Vector3();
			lookat.X = (float) (Math.Sin(orientation.X) * Math.Cos(orientation.Y));
			lookat.Y = (float) Math.Sin(orientation.Y);
			lookat.Z = (float) (Math.Cos(orientation.X) * Math.Cos(orientation.Y));
			return Matrix4.LookAt(position, position + lookat, Vector3.UnitY);
		}
		public void Move(float x, float y, float z) {
			Vector3 offset = new Vector3();
			Vector3 forward = new Vector3((float) Math.Sin((float) orientation.X), 0, (float) Math.Cos((float) orientation.X));
			Vector3 right = new Vector3(-forward.Z, 0, forward.X);
			offset += x * right;
			offset += y * forward;
			offset.Y += z;
			offset.NormalizeFast();
			offset = Vector3.Multiply(offset, moveSpeed);
			position += offset;
		}
		public void AddRotation(float x, float y) {
			x = x * sensitivity;
			y = y * sensitivity;
			orientation.X = (orientation.X + x) % ((float) Math.PI * 2.0f);
			orientation.Y = Math.Max(Math.Min(orientation.Y + y, (float) Math.PI / 2.0f - 0.1f), (float) -Math.PI / 2.0f + 0.1f);
		}
	}
	class Gwin: GameWindow {
		double counter = 0;
		Camera cam;
		Vector2 lastMousePos = new Vector2();
		public Gwin(int width, int height, GraphicsMode mode, string title): base(width, height, mode, title) {
			this.VSync = VSyncMode.On;
		}
		protected override void OnLoad(EventArgs e) {
			base.OnLoad(e);
			cam = new Camera();
			lastMousePos = new Vector2(OpenTK.Input.Mouse.GetState().X, OpenTK.Input.Mouse.GetState().Y);
			cam.position += new Vector3(0f, 0f, 3f);
		}
		protected override void OnRenderFrame(FrameEventArgs e) {
			base.OnRenderFrame(e);
			counter += e.Time;
			GL.Enable(EnableCap.DepthTest);
			GL.MatrixMode(MatrixMode.Modelview);
			Matrix4 modelview = Matrix4.LookAt(Vector3.Zero, Vector3.UnitZ, Vector3.UnitY);
			GL.LoadMatrix(ref modelview);
			Matrix4 perspective = cam.GetViewMatrix() * Matrix4.CreatePerspectiveFieldOfView(1.8f, 1.0f, 1.0f, 200.0f);
			GL.MatrixMode(MatrixMode.Projection);
			GL.LoadMatrix(ref perspective);
			GL.ClearColor(Color.CornflowerBlue);
			GL.Clear(ClearBufferMask.ColorBufferBit | ClearBufferMask.DepthBufferBit);
			GL.Material(MaterialFace.FrontAndBack, MaterialParameter.Specular, Color4.White);
			GL.Begin(PrimitiveType.Quads);
			GL.Normal3(Vector3.UnitX);
			GL.Vertex3(-10.0f, 10.0f, 10.0f);
			GL.Vertex3(-10.0f, -10.0f, 10.0f);
			GL.Vertex3(10.0f, -10.0f, 10.0f);
			GL.Vertex3(10.0f, 10.0f, 10.0f);
			GL.End();
			this.SwapBuffers();
		}
		protected override void OnUpdateFrame (FrameEventArgs e) {
			if (OpenTK.Input.Keyboard.GetState().IsKeyDown(Key.Escape))
			{
				Exit();
			}
			if (OpenTK.Input.Keyboard.GetState().IsKeyDown(Key.W))
			{
				cam.Move(0f, 0.1f, 0f);
			}
			if (OpenTK.Input.Keyboard.GetState().IsKeyDown(Key.S))
			{
				cam.Move(0f, -0.1f, 0f);
			}
			if (OpenTK.Input.Keyboard.GetState().IsKeyDown(Key.A))
			{
				cam.Move(-0.1f, 0f, 0f);
			}
			if (OpenTK.Input.Keyboard.GetState().IsKeyDown(Key.D))
			{
				cam.Move(0.1f, 0f, 0f);
			}
			if (OpenTK.Input.Keyboard.GetState().IsKeyDown(Key.Q))
			{
				cam.Move(0f, 0f, 0.1f);
			}
			if (OpenTK.Input.Keyboard.GetState().IsKeyDown(Key.E))
			{
				cam.Move(0f, 0f, -0.1f);
			}
		}
	}
	class Program {
		static void Main(string[] args) {
			Gwin window = new Gwin(500, 500, OpenTK.Graphics.GraphicsMode.Default, "Test");
			window.Run();
		}
	}
}

```

以上。