style: apply code-style cleanup (explicit types, this-qualification, switch expressions)

This commit is contained in:
2026-05-28 13:29:13 +02:00
parent 8e3195ca37
commit 70c986529b
9 changed files with 110 additions and 102 deletions

View File

@@ -30,28 +30,31 @@ public sealed class Game : GameWindow
GL.Enable(EnableCap.DepthTest); GL.Enable(EnableCap.DepthTest);
GL.Enable(EnableCap.CullFace); GL.Enable(EnableCap.CullFace);
_shader = new Shader("Assets/shaders/chunk.vert", "Assets/shaders/chunk.frag"); this._shader = new Shader("Assets/shaders/chunk.vert", "Assets/shaders/chunk.frag");
_texture = new Texture("Assets/textures/atlas.png"); this._texture = new Texture("Assets/textures/atlas.png");
Chunk chunk = BuildChunk(); Chunk chunk = this.BuildChunk();
float[] mesh = new ChunkMesher().Build(chunk, _registry); float[] mesh = new ChunkMesher().Build(chunk, this._registry);
_renderer = new ChunkRenderer(mesh); this._renderer = new ChunkRenderer(mesh);
_camera = new Camera(new Vector3(8f, 20f, 40f), ClientSize.X / (float)ClientSize.Y); this._camera = new Camera(new Vector3(8f, 20f, 40f), this.ClientSize.X / (float)this.ClientSize.Y);
CursorState = CursorState.Grabbed; this.CursorState = CursorState.Grabbed;
} }
private Chunk BuildChunk() private Chunk BuildChunk()
{ {
var chunk = new Chunk(); Chunk chunk = new();
for (int x = 0; x < Chunk.Size; x++) for (int x = 0; x < Chunk.Size; x++)
for (int z = 0; z < Chunk.Size; z++) for (int z = 0; z < Chunk.Size; z++)
for (int y = 0; y < Chunk.Size; y++) for (int y = 0; y < Chunk.Size; y++)
{ {
if (y == Chunk.Size - 1) chunk[x, y, z] = _registry.Grass.Id; chunk[x, y, z] = y switch
else if (y >= Chunk.Size - 4) chunk[x, y, z] = _registry.Dirt.Id; {
else chunk[x, y, z] = _registry.Stone.Id; Chunk.Size - 1 => this._registry.Grass.Id,
>= Chunk.Size - 4 => this._registry.Dirt.Id,
_ => this._registry.Stone.Id
};
} }
return chunk; return chunk;
} }
@@ -59,21 +62,21 @@ public sealed class Game : GameWindow
protected override void OnUpdateFrame(FrameEventArgs args) protected override void OnUpdateFrame(FrameEventArgs args)
{ {
base.OnUpdateFrame(args); base.OnUpdateFrame(args);
if (!IsFocused) return; if (!this.IsFocused) return;
KeyboardState keyboard = KeyboardState; if (this.KeyboardState.IsKeyDown(Keys.Escape)) {
if (keyboard.IsKeyDown(Keys.Escape)) { Close(); return; } this.Close(); return; }
float distance = MoveSpeed * (float)args.Time; float distance = Game.MoveSpeed * (float)args.Time;
if (keyboard.IsKeyDown(Keys.W)) _camera.Move(_camera.Front * distance); if (this.KeyboardState.IsKeyDown(Keys.W)) this._camera.Move(this._camera.Front * distance);
if (keyboard.IsKeyDown(Keys.S)) _camera.Move(-_camera.Front * distance); if (this.KeyboardState.IsKeyDown(Keys.S)) this._camera.Move(-this._camera.Front * distance);
if (keyboard.IsKeyDown(Keys.A)) _camera.Move(-_camera.Right * distance); if (this.KeyboardState.IsKeyDown(Keys.A)) this._camera.Move(-this._camera.Right * distance);
if (keyboard.IsKeyDown(Keys.D)) _camera.Move(_camera.Right * distance); if (this.KeyboardState.IsKeyDown(Keys.D)) this._camera.Move(this._camera.Right * distance);
if (keyboard.IsKeyDown(Keys.Space)) _camera.Move(Vector3.UnitY * distance); if (this.KeyboardState.IsKeyDown(Keys.Space)) this._camera.Move(Vector3.UnitY * distance);
if (keyboard.IsKeyDown(Keys.LeftShift)) _camera.Move(-Vector3.UnitY * distance); if (this.KeyboardState.IsKeyDown(Keys.LeftShift)) this._camera.Move(-Vector3.UnitY * distance);
Vector2 delta = MouseState.Delta; Vector2 delta = this.MouseState.Delta;
_camera.AddRotation(delta.X * Sensitivity, -delta.Y * Sensitivity); this._camera.AddRotation(delta.X * Game.Sensitivity, -delta.Y * Game.Sensitivity);
} }
protected override void OnRenderFrame(FrameEventArgs args) protected override void OnRenderFrame(FrameEventArgs args)
@@ -82,29 +85,30 @@ public sealed class Game : GameWindow
GL.Clear(ClearBufferMask.ColorBufferBit | ClearBufferMask.DepthBufferBit); GL.Clear(ClearBufferMask.ColorBufferBit | ClearBufferMask.DepthBufferBit);
_shader.Use(); this._shader.Use();
_shader.SetMatrix4("model", Matrix4.Identity); this._shader.SetMatrix4("model", Matrix4.Identity);
_shader.SetMatrix4("view", _camera.GetViewMatrix()); this._shader.SetMatrix4("view", this._camera.GetViewMatrix());
_shader.SetMatrix4("projection", _camera.GetProjectionMatrix()); this._shader.SetMatrix4("projection", this._camera.GetProjectionMatrix());
_shader.SetInt("atlas", 0); this._shader.SetInt("atlas", 0);
_texture.Use(TextureUnit.Texture0); this._texture.Use(TextureUnit.Texture0);
_renderer.Draw(); this._renderer.Draw();
SwapBuffers(); this.SwapBuffers();
} }
protected override void OnResize(ResizeEventArgs e) protected override void OnResize(ResizeEventArgs e)
{ {
base.OnResize(e); base.OnResize(e);
GL.Viewport(0, 0, e.Width, e.Height); GL.Viewport(0, 0, e.Width, e.Height);
if (_camera is not null) _camera.AspectRatio = e.Width / (float)e.Height; // OnResize can fire before OnLoad (where _camera is created), so guard against it.
if (this._camera is not null) this._camera.AspectRatio = e.Width / (float)e.Height;
} }
protected override void OnUnload() protected override void OnUnload()
{ {
_renderer.Dispose(); this._renderer.Dispose();
_texture.Dispose(); this._texture.Dispose();
_shader.Dispose(); this._shader.Dispose();
base.OnUnload(); base.OnUnload();
} }
} }

View File

@@ -3,7 +3,7 @@ using OpenTK.Windowing.Common;
using OpenTK.Windowing.Desktop; using OpenTK.Windowing.Desktop;
using VoxelEngine.Core; using VoxelEngine.Core;
var nativeSettings = new NativeWindowSettings NativeWindowSettings nativeSettings = new()
{ {
ClientSize = new Vector2i(1280, 720), ClientSize = new Vector2i(1280, 720),
Title = "VoxelEngine", Title = "VoxelEngine",
@@ -12,5 +12,5 @@ var nativeSettings = new NativeWindowSettings
Flags = ContextFlags.ForwardCompatible Flags = ContextFlags.ForwardCompatible
}; };
using var game = new Game(GameWindowSettings.Default, nativeSettings); using Game game = new(GameWindowSettings.Default, nativeSettings);
game.Run(); game.Run();

View File

@@ -8,7 +8,7 @@ public sealed class Camera
public Vector3 Position { get; private set; } public Vector3 Position { get; private set; }
public float Yaw { get; private set; } = -90f; // degrees; -90 looks down -Z public float Yaw { get; private set; } = -90f; // degrees; -90 looks down -Z
public float Pitch { get; private set; } = 0f; // degrees public float Pitch { get; private set; } // degrees
public float Fov { get; set; } = 60f; // degrees public float Fov { get; set; } = 60f; // degrees
public float AspectRatio { get; set; } public float AspectRatio { get; set; }
@@ -18,37 +18,37 @@ public sealed class Camera
public Camera(Vector3 position, float aspectRatio) public Camera(Vector3 position, float aspectRatio)
{ {
Position = position; this.Position = position;
AspectRatio = aspectRatio; this.AspectRatio = aspectRatio;
UpdateVectors(); this.UpdateVectors();
} }
public void Move(Vector3 delta) => Position += delta; public void Move(Vector3 delta) => this.Position += delta;
public void AddRotation(float yawDelta, float pitchDelta) public void AddRotation(float yawDelta, float pitchDelta)
{ {
Yaw += yawDelta; this.Yaw += yawDelta;
Pitch = MathHelper.Clamp(Pitch + pitchDelta, -89f, 89f); this.Pitch = MathHelper.Clamp(this.Pitch + pitchDelta, -89f, 89f);
UpdateVectors(); this.UpdateVectors();
} }
public Matrix4 GetViewMatrix() => Matrix4.LookAt(Position, Position + Front, Up); public Matrix4 GetViewMatrix() => Matrix4.LookAt(this.Position, this.Position + this.Front, this.Up);
public Matrix4 GetProjectionMatrix() => public Matrix4 GetProjectionMatrix() =>
Matrix4.CreatePerspectiveFieldOfView( Matrix4.CreatePerspectiveFieldOfView(
MathHelper.DegreesToRadians(Fov), AspectRatio, 0.1f, 100f); MathHelper.DegreesToRadians(this.Fov), this.AspectRatio, 0.1f, 100f);
private void UpdateVectors() private void UpdateVectors()
{ {
float yaw = MathHelper.DegreesToRadians(Yaw); float yaw = MathHelper.DegreesToRadians(this.Yaw);
float pitch = MathHelper.DegreesToRadians(Pitch); float pitch = MathHelper.DegreesToRadians(this.Pitch);
Front = Vector3.Normalize(new Vector3( this.Front = Vector3.Normalize(new Vector3(
MathF.Cos(yaw) * MathF.Cos(pitch), MathF.Cos(yaw) * MathF.Cos(pitch),
MathF.Sin(pitch), MathF.Sin(pitch),
MathF.Sin(yaw) * MathF.Cos(pitch))); MathF.Sin(yaw) * MathF.Cos(pitch)));
Right = Vector3.Normalize(Vector3.Cross(Front, WorldUp)); this.Right = Vector3.Normalize(Vector3.Cross(this.Front, Camera.WorldUp));
Up = Vector3.Normalize(Vector3.Cross(Right, Front)); this.Up = Vector3.Normalize(Vector3.Cross(this.Right, this.Front));
} }
} }

View File

@@ -12,14 +12,14 @@ public sealed class ChunkRenderer : IDisposable
public ChunkRenderer(float[] vertices) public ChunkRenderer(float[] vertices)
{ {
_vertexCount = vertices.Length / FloatsPerVertex; this._vertexCount = vertices.Length / ChunkRenderer.FloatsPerVertex;
int stride = FloatsPerVertex * sizeof(float); int stride = ChunkRenderer.FloatsPerVertex * sizeof(float);
_vao = GL.GenVertexArray(); this._vao = GL.GenVertexArray();
GL.BindVertexArray(_vao); GL.BindVertexArray(this._vao);
_vbo = GL.GenBuffer(); this._vbo = GL.GenBuffer();
GL.BindBuffer(BufferTarget.ArrayBuffer, _vbo); GL.BindBuffer(BufferTarget.ArrayBuffer, this._vbo);
GL.BufferData(BufferTarget.ArrayBuffer, vertices.Length * sizeof(float), vertices, BufferUsageHint.StaticDraw); GL.BufferData(BufferTarget.ArrayBuffer, vertices.Length * sizeof(float), vertices, BufferUsageHint.StaticDraw);
// location 0: position (vec3) at offset 0 // location 0: position (vec3) at offset 0
@@ -39,14 +39,14 @@ public sealed class ChunkRenderer : IDisposable
public void Draw() public void Draw()
{ {
GL.BindVertexArray(_vao); GL.BindVertexArray(this._vao);
GL.DrawArrays(PrimitiveType.Triangles, 0, _vertexCount); GL.DrawArrays(PrimitiveType.Triangles, 0, this._vertexCount);
GL.BindVertexArray(0); GL.BindVertexArray(0);
} }
public void Dispose() public void Dispose()
{ {
GL.DeleteBuffer(_vbo); GL.DeleteBuffer(this._vbo);
GL.DeleteVertexArray(_vao); GL.DeleteVertexArray(this._vao);
} }
} }

View File

@@ -10,38 +10,38 @@ public sealed class Shader : IDisposable
public Shader(string vertexPath, string fragmentPath) public Shader(string vertexPath, string fragmentPath)
{ {
int vertex = CompileFromFile(ShaderType.VertexShader, vertexPath); int vertex = Shader.CompileFromFile(ShaderType.VertexShader, vertexPath);
int fragment = CompileFromFile(ShaderType.FragmentShader, fragmentPath); int fragment = Shader.CompileFromFile(ShaderType.FragmentShader, fragmentPath);
_handle = GL.CreateProgram(); this._handle = GL.CreateProgram();
GL.AttachShader(_handle, vertex); GL.AttachShader(this._handle, vertex);
GL.AttachShader(_handle, fragment); GL.AttachShader(this._handle, fragment);
GL.LinkProgram(_handle); GL.LinkProgram(this._handle);
GL.GetProgram(_handle, GetProgramParameterName.LinkStatus, out int linked); GL.GetProgram(this._handle, GetProgramParameterName.LinkStatus, out int linked);
if (linked == 0) if (linked == 0)
throw new InvalidOperationException($"Program link failed: {GL.GetProgramInfoLog(_handle)}"); throw new InvalidOperationException($"Program link failed: {GL.GetProgramInfoLog(this._handle)}");
GL.DetachShader(_handle, vertex); GL.DetachShader(this._handle, vertex);
GL.DetachShader(_handle, fragment); GL.DetachShader(this._handle, fragment);
GL.DeleteShader(vertex); GL.DeleteShader(vertex);
GL.DeleteShader(fragment); GL.DeleteShader(fragment);
} }
public void Use() => GL.UseProgram(_handle); public void Use() => GL.UseProgram(this._handle);
public void SetMatrix4(string name, Matrix4 value) => public void SetMatrix4(string name, Matrix4 value) =>
GL.UniformMatrix4(Location(name), true, ref value); GL.UniformMatrix4(this.Location(name), true, ref value);
public void SetInt(string name, int value) => public void SetInt(string name, int value) =>
GL.Uniform1(Location(name), value); GL.Uniform1(this.Location(name), value);
private int Location(string name) private int Location(string name)
{ {
if (!_uniforms.TryGetValue(name, out int location)) if (!this._uniforms.TryGetValue(name, out int location))
{ {
location = GL.GetUniformLocation(_handle, name); location = GL.GetUniformLocation(this._handle, name);
_uniforms[name] = location; this._uniforms[name] = location;
} }
return location; return location;
} }
@@ -60,5 +60,5 @@ public sealed class Shader : IDisposable
return shader; return shader;
} }
public void Dispose() => GL.DeleteProgram(_handle); public void Dispose() => GL.DeleteProgram(this._handle);
} }

View File

@@ -9,8 +9,8 @@ public sealed class Texture : IDisposable
public Texture(string path) public Texture(string path)
{ {
_handle = GL.GenTexture(); this._handle = GL.GenTexture();
GL.BindTexture(TextureTarget.Texture2D, _handle); GL.BindTexture(TextureTarget.Texture2D, this._handle);
StbImage.stbi_set_flip_vertically_on_load(1); StbImage.stbi_set_flip_vertically_on_load(1);
using FileStream stream = File.OpenRead(path); using FileStream stream = File.OpenRead(path);
@@ -28,8 +28,8 @@ public sealed class Texture : IDisposable
public void Use(TextureUnit unit = TextureUnit.Texture0) public void Use(TextureUnit unit = TextureUnit.Texture0)
{ {
GL.ActiveTexture(unit); GL.ActiveTexture(unit);
GL.BindTexture(TextureTarget.Texture2D, _handle); GL.BindTexture(TextureTarget.Texture2D, this._handle);
} }
public void Dispose() => GL.DeleteTexture(_handle); public void Dispose() => GL.DeleteTexture(this._handle);
} }

View File

@@ -14,13 +14,13 @@ public sealed class BlockRegistry
public BlockRegistry() public BlockRegistry()
{ {
// Index by id. Order does not matter; slot = block.Id. // Index by id. Order does not matter; slot = block.Id.
var blocks = new IBlock[] { Air, Stone, Dirt, Grass }; IBlock[] blocks = new IBlock[] { this.Air, this.Stone, this.Dirt, this.Grass };
_byId = new IBlock[blocks.Length]; this._byId = new IBlock[blocks.Length];
foreach (IBlock block in blocks) foreach (IBlock block in blocks)
{ {
_byId[block.Id] = block; this._byId[block.Id] = block;
} }
} }
public IBlock Get(ushort id) => _byId[id]; public IBlock Get(ushort id) => this._byId[id];
} }

View File

@@ -4,16 +4,16 @@ public sealed class Chunk
{ {
public const int Size = 16; public const int Size = 16;
private readonly ushort[] _ids = new ushort[Size * Size * Size]; private readonly ushort[] _ids = new ushort[Chunk.Size * Chunk.Size * Chunk.Size];
public ushort this[int x, int y, int z] public ushort this[int x, int y, int z]
{ {
get => _ids[Index(x, y, z)]; get => this._ids[Chunk.Index(x, y, z)];
set => _ids[Index(x, y, z)] = value; set => this._ids[Chunk.Index(x, y, z)] = value;
} }
public static bool InBounds(int x, int y, int z) => public static bool InBounds(int x, int y, int z) =>
x >= 0 && x < Size && y >= 0 && y < Size && z >= 0 && z < Size; x is >= 0 and < Chunk.Size && y is >= 0 and < Chunk.Size && z is >= 0 and < Chunk.Size;
private static int Index(int x, int y, int z) => (x * Size + y) * Size + z; private static int Index(int x, int y, int z) => (x * Chunk.Size + y) * Chunk.Size + z;
} }

View File

@@ -21,7 +21,12 @@ public sealed class ChunkMesher : IChunkMesher
(float, float, float) @base, (float, float, float) u, (float, float, float) @base, (float, float, float) u,
(float, float, float) v, float shade) (float, float, float) v, float shade)
{ {
Kind = kind; Normal = normal; Base = @base; U = u; V = v; Shade = shade; this.Kind = kind;
this.Normal = normal;
this.Base = @base;
this.U = u;
this.V = v;
this.Shade = shade;
} }
} }
@@ -42,7 +47,7 @@ public sealed class ChunkMesher : IChunkMesher
public float[] Build(Chunk chunk, BlockRegistry registry) public float[] Build(Chunk chunk, BlockRegistry registry)
{ {
var verts = new List<float>(); List<float> verts = new();
for (int x = 0; x < Chunk.Size; x++) for (int x = 0; x < Chunk.Size; x++)
for (int y = 0; y < Chunk.Size; y++) for (int y = 0; y < Chunk.Size; y++)
@@ -51,7 +56,7 @@ public sealed class ChunkMesher : IChunkMesher
IBlock block = registry.Get(chunk[x, y, z]); IBlock block = registry.Get(chunk[x, y, z]);
if (!block.IsOpaque) continue; if (!block.IsOpaque) continue;
foreach (Face face in Faces) foreach (Face face in ChunkMesher.Faces)
{ {
int nx = x + face.Normal.x; int nx = x + face.Normal.x;
int ny = y + face.Normal.y; int ny = y + face.Normal.y;
@@ -62,7 +67,7 @@ public sealed class ChunkMesher : IChunkMesher
Chunk.InBounds(nx, ny, nz) && registry.Get(chunk[nx, ny, nz]).IsOpaque; Chunk.InBounds(nx, ny, nz) && registry.Get(chunk[nx, ny, nz]).IsOpaque;
if (neighborOpaque) continue; if (neighborOpaque) continue;
AddFace(verts, x, y, z, face, block.GetTextureIndex(face.Kind)); ChunkMesher.AddFace(verts, x, y, z, face, block.GetTextureIndex(face.Kind));
} }
} }
@@ -71,22 +76,21 @@ public sealed class ChunkMesher : IChunkMesher
private static void AddFace(List<float> verts, int x, int y, int z, Face face, int texIndex) private static void AddFace(List<float> verts, int x, int y, int z, Face face, int texIndex)
{ {
float tileWidth = 1f / AtlasTiles; float tileWidth = 1f / ChunkMesher.AtlasTiles;
float uBase = texIndex * tileWidth; float uBase = texIndex * tileWidth;
foreach (int corner in Triangle) foreach (int corner in ChunkMesher.Triangle)
{ {
(float cu, float cv) = Corners[corner]; (float cu, float cv) = ChunkMesher.Corners[corner];
float px = x + face.Base.x + face.U.x * cu + face.V.x * cv; float px = x + face.Base.x + face.U.x * cu + face.V.x * cv;
float py = y + face.Base.y + face.U.y * cu + face.V.y * cv; float py = y + face.Base.y + face.U.y * cu + face.V.y * cv;
float pz = z + face.Base.z + face.U.z * cu + face.V.z * cv; float pz = z + face.Base.z + face.U.z * cu + face.V.z * cv;
float u = uBase + cu * tileWidth; float u = uBase + cu * tileWidth;
float v = cv;
verts.Add(px); verts.Add(py); verts.Add(pz); verts.Add(px); verts.Add(py); verts.Add(pz);
verts.Add(u); verts.Add(v); verts.Add(u); verts.Add(cv);
verts.Add(face.Shade); verts.Add(face.Shade);
} }
} }