mirror of
https://github.com/UOH-CS-Level5/551455-graphics-programming-2526-the-repo-Zyb3rWolfi.git
synced 2025-11-29 00:43:08 +00:00
239 lines
8.9 KiB
C#
239 lines
8.9 KiB
C#
using Assimp;
|
|
using OpenTK.Graphics.OpenGL4;
|
|
using OpenTK.Windowing.Common;
|
|
using OpenTK.Windowing.GraphicsLibraryFramework;
|
|
using OpenTK.Windowing.Desktop;
|
|
using LearnOpenTK.Common;
|
|
using OpenTK.Mathematics;
|
|
using TheLabs.Shapes;
|
|
|
|
namespace TheLabs
|
|
{
|
|
public class MyExampleWindow : GameWindow
|
|
{
|
|
|
|
// -- Scene Graph Nodes
|
|
private SceneNode _rootNode;
|
|
private SceneNode _characterNode;
|
|
private SceneNode _buildingNode;
|
|
|
|
// -- OpenGL Resources
|
|
private Shader _shader;
|
|
private Camera _camera;
|
|
|
|
// - Resources that only need to be created once
|
|
private Mesh _exampleObject;
|
|
private Mesh _buildingObject;
|
|
private Texture _texture;
|
|
private RenderObject _render;
|
|
private RenderObject _buildingRender;
|
|
|
|
// Camera parameters
|
|
private Vector3 _cameraPosition = new Vector3(0.0f, 0.0f, -3.0f);
|
|
private Vector3 _cameraFront = new Vector3(0.0f, 0.0f, -1.0f);
|
|
private Vector3 _cameraUp = Vector3.UnitY;
|
|
private float _yaw = -90.0f;
|
|
private float _cameraSpeed = 2.5f;
|
|
private float _rotationSpeed = 50.0f;
|
|
private float _mouseSensitivity = 0.1f;
|
|
private float _pitch = 0.0f;
|
|
private float _rotation = 0.0f;
|
|
|
|
// Materials and Lighting
|
|
private Lighting _mainLight;
|
|
private Material _defaultMaterial;
|
|
|
|
// This prevents a large camera jump when the window first gets focus
|
|
private bool _firstMove = true;
|
|
|
|
public MyExampleWindow(GameWindowSettings gameWindowSettings, NativeWindowSettings nativeWindowSettings)
|
|
: base(gameWindowSettings, nativeWindowSettings)
|
|
{
|
|
}
|
|
|
|
// Now, we start initializing OpenGL.
|
|
protected override void OnLoad()
|
|
{
|
|
// This is called when the window is created and is where we can set up OpenGL resources.
|
|
base.OnLoad();
|
|
|
|
// --- Set up Lighting and Material ---
|
|
_mainLight = new Lighting(new Vector3(
|
|
1.2f, 1.0f, 2.0f),
|
|
new Vector3(5.0f),
|
|
new Vector3(1.5f),
|
|
new Vector3(4.0f));
|
|
|
|
_defaultMaterial = new Material(
|
|
new Vector3(0.5f, 0.5f, 0.5f) * 0.1f,
|
|
new Vector3(0.5f, 0.5f, 0.5f) * 0.6f,
|
|
new Vector3(1.0f, 1.0f, 1.0f),
|
|
32.0f);
|
|
|
|
// --- Set up OpenGL State ---
|
|
GL.ClearColor(0.2f, 0.3f, 0.3f, 1.0f);
|
|
GL.Enable(EnableCap.DepthTest);
|
|
|
|
// --- Set up Camera ---
|
|
_camera = new Camera(_cameraPosition, _cameraFront, _cameraUp);
|
|
|
|
// -- Load Shaders, Textures, and Create Scene Objects ---
|
|
_shader = new Shader("Shaders/shader.vert", "Shaders/shader.frag");
|
|
_texture = new Texture("Textures/cobble.jpg");
|
|
Texture _normalMap = new Texture("Textures/cobbleNormal.jpg");
|
|
|
|
|
|
// --- Create Scene Graph ---
|
|
_rootNode = new SceneNode();
|
|
|
|
// Create Example Object
|
|
_buildingObject = ShapeFactory.CreateTexturedCube();
|
|
_buildingRender = new RenderObject(_buildingObject, _shader, _texture, _defaultMaterial, _mainLight);
|
|
_buildingRender.NormalMap = _normalMap;
|
|
_buildingNode = new SceneNode(_buildingRender);
|
|
_buildingNode.Position = new Vector3(2.0f, -1.0f, 0.0f);
|
|
_buildingNode.Scale = new Vector3(0.9f, 0.1f, 0.1f);
|
|
_rootNode.AddChild(_buildingNode);
|
|
|
|
// Create Character Object
|
|
CursorState = CursorState.Grabbed;
|
|
|
|
|
|
|
|
}
|
|
|
|
// Now that initialization is done, let's create our render loop.
|
|
protected override void OnRenderFrame(FrameEventArgs e)
|
|
{
|
|
// This is called once per frame and is where all the rendering code goes.
|
|
base.OnRenderFrame(e);
|
|
// Clear the color buffer and the depth buffer
|
|
GL.Clear(ClearBufferMask.DepthBufferBit | ClearBufferMask.ColorBufferBit);
|
|
|
|
// --- Set up Camera ---
|
|
Matrix4 view = _camera.LookAt();
|
|
float aspectRatio = (float)Size.X / Size.Y;
|
|
|
|
// 2. Add a safety check for divide-by-zero
|
|
if (Size.Y == 0 || Size.X == 0)
|
|
{
|
|
aspectRatio = 1.0f; // Default to 1:1 if window is minimized
|
|
}
|
|
|
|
// 3. Create the projection matrix
|
|
Matrix4 projection = Matrix4.CreatePerspectiveFieldOfView(
|
|
MathHelper.DegreesToRadians(45f),
|
|
aspectRatio,
|
|
0.1f,
|
|
100.0f
|
|
);
|
|
|
|
// --- Draw Scene Objects ---
|
|
_rootNode.Draw(view, projection, Matrix4.Identity, _mainLight);
|
|
SwapBuffers();
|
|
}
|
|
|
|
protected override void OnUpdateFrame(FrameEventArgs e)
|
|
{
|
|
base.OnUpdateFrame(e);
|
|
_rotation += (float)e.Time;
|
|
var input = KeyboardState;
|
|
|
|
if (input.IsKeyDown(Keys.Escape))
|
|
{
|
|
Close();
|
|
}
|
|
|
|
if (!IsFocused)
|
|
{
|
|
_firstMove = true;
|
|
return;
|
|
}
|
|
|
|
var mouuse = MouseState;
|
|
|
|
if (_firstMove)
|
|
{
|
|
mouuse = MouseState;
|
|
_firstMove = false;
|
|
}
|
|
else
|
|
{
|
|
// Get the mouse's movement delta
|
|
float deltaX = mouuse.Delta.X;
|
|
float deltaY = mouuse.Delta.Y;
|
|
|
|
// Apply sensitivity
|
|
_yaw += deltaX * _mouseSensitivity;
|
|
_pitch -= deltaY * _mouseSensitivity; // Y-axis is inverted
|
|
}
|
|
|
|
|
|
// --- Rotation (Arrow Keys) ---
|
|
if (input.IsKeyDown(Keys.Left))
|
|
{
|
|
_yaw -= _rotationSpeed * (float)e.Time;
|
|
}
|
|
if (input.IsKeyDown(Keys.Right))
|
|
{
|
|
_yaw += _rotationSpeed * (float)e.Time;
|
|
}
|
|
if (input.IsKeyDown(Keys.Up))
|
|
{
|
|
_pitch += _rotationSpeed * (float)e.Time;
|
|
}
|
|
if (input.IsKeyDown(Keys.Down))
|
|
{
|
|
_pitch -= _rotationSpeed * (float)e.Time;
|
|
}
|
|
_pitch = MathHelper.Clamp(_pitch, -89.0f, 89.0f);
|
|
Vector3 front;
|
|
_camera._target.X = MathF.Cos(MathHelper.DegreesToRadians(_yaw)) * MathF.Cos(MathHelper.DegreesToRadians(_pitch));
|
|
_camera._target.Y = MathF.Sin(MathHelper.DegreesToRadians(_pitch));
|
|
_camera._target.Z = MathF.Sin(MathHelper.DegreesToRadians(_yaw)) * MathF.Cos(MathHelper.DegreesToRadians(_pitch));
|
|
|
|
_cameraFront = Vector3.Normalize(_camera._target);
|
|
var _cameraRight = Vector3.Normalize(Vector3.Cross(_cameraFront, _camera._up));
|
|
if (input.IsKeyDown(Keys.W)) _camera._position += _cameraFront * _cameraSpeed * (float)e.Time;
|
|
if (input.IsKeyDown(Keys.S)) _camera._position -= _cameraFront * _cameraSpeed * (float)e.Time;
|
|
if (input.IsKeyDown(Keys.A)) _camera._position -= _cameraRight * _cameraSpeed * (float)e.Time;
|
|
if (input.IsKeyDown(Keys.D)) _camera._position += _cameraRight * _cameraSpeed * (float)e.Time;
|
|
|
|
}
|
|
|
|
|
|
protected override void OnResize(ResizeEventArgs e)
|
|
{
|
|
base.OnResize(e);
|
|
|
|
// When the window gets resized, we have to call GL.Viewport to resize OpenGL's viewport to match the new size.
|
|
// If we don't, the NDC will no longer be correct.
|
|
GL.Viewport(0, 0, Size.X, Size.Y);
|
|
}
|
|
|
|
// Now, for cleanup.
|
|
// You should generally not do cleanup of opengl resources when exiting an application,
|
|
// as that is handled by the driver and operating system when the application exits.
|
|
//
|
|
// There are reasons to delete opengl resources, but exiting the application is not one of them.
|
|
// This is provided here as a reference on how resource cleanup is done in opengl, but
|
|
// should not be done when exiting the application.
|
|
//
|
|
// Places where cleanup is appropriate would be: to delete textures that are no
|
|
// longer used for whatever reason (e.g. a new scene is loaded that doesn't use a texture).
|
|
// This would free up video ram (VRAM) that can be used for new textures.
|
|
//
|
|
// The coming chapters will not have this code.
|
|
protected override void OnUnload()
|
|
{
|
|
// Unbind all the resources by binding the targets to 0/null.
|
|
GL.BindBuffer(BufferTarget.ArrayBuffer, 0);
|
|
GL.BindVertexArray(0);
|
|
GL.UseProgram(0);
|
|
|
|
GL.DeleteProgram(_shader.Handle);
|
|
|
|
base.OnUnload();
|
|
}
|
|
}
|
|
} |