CCCPaste

OpenGL C# FP Camera and Cube

/*
 * Created by SharpDevelop.
 * User: OgreVorbis
 * Date: 1/1/2022
 * Time: 9:19 PM
 * 
 * This will render a cube(s) with OpenTK at a specific world positions and create an FPS style camera.
 * The OpenTK FPS camera sample has some bugs and isn't written in a straightforward way.
 * This will start you on a path of a Minecraft type game or anything else based on rendering lots of cubes.
 * You need OpenTK 3.3.1 and a reference to system drawing.
 */
using System;
using OpenTK;
using OpenTK.Graphics;
using OpenTK.Graphics.OpenGL;
using OpenTK.Input;

namespace OpenTKTest
{
    class Game : GameWindow
    {
    	const float speed = 0.12f;
    	const float sensitivity = 0.16f;
    	float pitch = 0.0f;
    	float yaw = -90.0f;
    	
    	bool firstMove = true;
		
    	Vector2 lastPos;
		Vector3 position = new Vector3(0.0f, 0.0f, 5.0f);
		Vector3 front = new Vector3(0.0f, 0.0f, -2.0f);
		Vector3 up = new Vector3(0.0f, 2.0f, 0.0f);
		
        public Game() : base(800, 600, GraphicsMode.Default, "OpenTK Cube and Camera")
        {
            VSync = VSyncMode.On;
        }

        void drawCube(float x, float y, float z)
		{
		    const float sizex = 0.5f;
		    const float sizey = 0.5f;
		    const float sizez = 0.5f;
		
		    GL.Translate(-x, -y, -z);
		
		    GL.Begin(PrimitiveType.Quads);
		
		    GL.Color3(1.0, 1.0, 0.0);
		
		    // FRONT
		    GL.Vertex3(-sizex, -sizey, sizez);
		    GL.Vertex3(sizex, -sizey, sizez);
		    GL.Vertex3(sizex, sizey, sizez);
		    GL.Vertex3(-sizex, sizey, sizez);
		
		    // BACK
		    GL.Vertex3(-sizex, -sizey, -sizez);
		    GL.Vertex3(-sizex, sizey, -sizez);
		    GL.Vertex3(sizex, sizey, -sizez);
		    GL.Vertex3(sizex, -sizey, -sizez);
		
		    GL.Color3(0.0, 1.0, 0.0);
		
		    // LEFT
		    GL.Vertex3(-sizex, -sizey, sizez);
		    GL.Vertex3(-sizex, sizey, sizez);
		    GL.Vertex3(-sizex, sizey, -sizez);
		    GL.Vertex3(-sizex, -sizey, -sizez);
		
		    // RIGHT
		    GL.Vertex3(sizex, -sizey, -sizez);
		    GL.Vertex3(sizex, sizey, -sizez);
		    GL.Vertex3(sizex, sizey, sizez);
		    GL.Vertex3(sizex, -sizey, sizez);
		
		    //GL.Color3(1.0, 0.0, 1.0);
		    // we test if we can use bytes here for later - yes we can
		    GL.Color3((byte)255, (byte)0, (byte)255);
		
		    // TOP
		    GL.Vertex3(-sizex, sizey, sizez);
		    GL.Vertex3(sizex, sizey, sizez);
		    GL.Vertex3(sizex, sizey, -sizez);
		    GL.Vertex3(-sizex, sizey, -sizez);
		
		    // BOTTOM
		    GL.Vertex3(-sizex, -sizey, sizez);
		    GL.Vertex3(-sizex, -sizey, -sizez);
		    GL.Vertex3(sizex, -sizey, -sizez);
		    GL.Vertex3(sizex, -sizey, sizez);
		
		    GL.End();
		
		    GL.Translate(x, y, z);
		}
        
        protected override void OnLoad(EventArgs e)
        {
            base.OnLoad(e);

            GL.ClearColor(0.1f, 0.2f, 0.5f, 0.0f);
            GL.Enable(EnableCap.DepthTest);
            
            CursorGrabbed = true;
            CursorVisible = false;
        }

        protected override void OnResize(EventArgs e)
        {
            base.OnResize(e);

            GL.Viewport(ClientRectangle.X, ClientRectangle.Y, ClientRectangle.Width, ClientRectangle.Height);

            Matrix4 projection = Matrix4.CreatePerspectiveFieldOfView((float)Math.PI / 4, Width / (float)Height, 1.0f, 64.0f);
            GL.MatrixMode(MatrixMode.Projection);
            GL.LoadMatrix(ref projection);
        }
        
        // MIGHT NOT NEED THIS FUNCTION
        protected override void OnMouseMove(MouseMoveEventArgs e)
		{
		    if (Focused) // check to see if the window is focused  
		    {
		        Mouse.SetPosition(X + Width / 2f, Y + Height / 2f);
		    }
		
		    base.OnMouseMove(e);
		}

        protected override void OnUpdateFrame(FrameEventArgs e)
        {
            base.OnUpdateFrame(e);

            if (!Focused) // check to see if the window is focused
		    {
		        return;
		    }
		
		    KeyboardState input = Keyboard.GetState();
		    MouseState mouse = Mouse.GetState();
		
		    // KEYBOARD MOVEMENT SECTION
		    if (input.IsKeyDown(Key.W))
		        position += front * speed; //Forward 

		    if (input.IsKeyDown(Key.S))
		        position -= front * speed; //Backwards

		    if (input.IsKeyDown(Key.A))
		        position -= Vector3.Normalize(Vector3.Cross(front, up)) * speed; //Left
		
		    if (input.IsKeyDown(Key.D))
		        position += Vector3.Normalize(Vector3.Cross(front, up)) * speed; //Right
		
		    if (input.IsKeyDown(Key.Space))
		        position += up * speed; //Up
		
		    if (input.IsKeyDown(Key.LShift))
		        position -= up * speed; //Down
		    
		    if (input.IsKeyDown(Key.Escape))
		    {
		    	CursorGrabbed = false;
		    	CursorVisible = true;
		    }
		    
		    
		    // MOUSE MOVEMENT SECTION
		    if (firstMove)
		    {
		        lastPos = new Vector2(mouse.X, mouse.Y);
		        firstMove = false;
		    }
		    else
		    {
		        float deltaX = mouse.X - lastPos.X;
		        float deltaY = mouse.Y - lastPos.Y;
		        lastPos = new Vector2(mouse.X, mouse.Y);
		
		        yaw += deltaX * sensitivity;
		        pitch -= deltaY * sensitivity;
		        if(pitch > 89.0f)
		            pitch = 89.0f;
		        else if(pitch < -89.0f)
		            pitch = -89.0f;
		        	
		    }
		    
		    front.X = (float)Math.Cos(MathHelper.DegreesToRadians(pitch)) * (float)Math.Cos(MathHelper.DegreesToRadians(yaw));
		    front.Y = (float)Math.Sin(MathHelper.DegreesToRadians(pitch));
		    front.Z = (float)Math.Cos(MathHelper.DegreesToRadians(pitch)) * (float)Math.Sin(MathHelper.DegreesToRadians(yaw));
		    front = Vector3.Normalize(front);
        }

        protected override void OnRenderFrame(FrameEventArgs e)
        {
            base.OnRenderFrame(e);

            GL.Clear(ClearBufferMask.ColorBufferBit | ClearBufferMask.DepthBufferBit);
            
            Matrix4 modelview = Matrix4.LookAt(position, position + front, up);
            GL.MatrixMode(MatrixMode.Modelview);
            GL.LoadMatrix(ref modelview);
            
            drawCube(0.0f, 0.0f, -2.0f);

            SwapBuffers();
        }

        [STAThread]
        public static void Main(string[] args)
        {
            using (Game game = new Game())
            {
                game.Run(60.0);
            }
        }
    }
}