using OpenTK.Mathematics; namespace VoxelEngine.Rendering; public sealed class Camera { private static readonly Vector3 WorldUp = Vector3.UnitY; public Vector3 Position { get; private set; } public float Yaw { get; private set; } = -90f; // degrees; -90 looks down -Z public float Pitch { get; private set; } // degrees public float Fov { get; set; } = 60f; // degrees public float FarPlane { get; set; } = 100f; // world units public float AspectRatio { get; set; } public Vector3 Front { get; private set; } = -Vector3.UnitZ; public Vector3 Right { get; private set; } = Vector3.UnitX; public Vector3 Up { get; private set; } = Vector3.UnitY; public Camera(Vector3 position, float aspectRatio) { this.Position = position; this.AspectRatio = aspectRatio; this.UpdateVectors(); } public void Move(Vector3 delta) => this.Position += delta; public void AddRotation(float yawDelta, float pitchDelta) { this.Yaw += yawDelta; this.Pitch = MathHelper.Clamp(this.Pitch + pitchDelta, -89f, 89f); this.UpdateVectors(); } public Matrix4 GetViewMatrix() => Matrix4.LookAt(this.Position, this.Position + this.Front, this.Up); public Matrix4 GetProjectionMatrix() => Matrix4.CreatePerspectiveFieldOfView( MathHelper.DegreesToRadians(this.Fov), this.AspectRatio, 0.1f, this.FarPlane); private void UpdateVectors() { float yaw = MathHelper.DegreesToRadians(this.Yaw); float pitch = MathHelper.DegreesToRadians(this.Pitch); this.Front = Vector3.Normalize(new Vector3( MathF.Cos(yaw) * MathF.Cos(pitch), MathF.Sin(pitch), MathF.Sin(yaw) * MathF.Cos(pitch))); this.Right = Vector3.Normalize(Vector3.Cross(this.Front, Camera.WorldUp)); this.Up = Vector3.Normalize(Vector3.Cross(this.Right, this.Front)); } }