2025-11-11 15:35:10 +00:00

132 lines
4.6 KiB
C#

namespace TheLabs;
using LearnOpenTK.Common;
using OpenTK.Graphics.OpenGL4;
using OpenTK.Mathematics;
using OpenTK.Windowing.Desktop;
using StbImageSharp;
public class Mesh : IDisposable
{
private readonly int _vao;
private readonly int _vbo;
private readonly int _ebo;
private readonly int _vertexCount;
private readonly bool _useIndices;
// A flexible way to define vertex layout
// (Could be an enum or a struct)
public enum VertexLayout { PosColor, PosTex }
public Mesh(float[] vertices, uint[] indices, VertexLayout layout)
{
_vertexCount = indices.Length;
_useIndices = true;
_vao = GL.GenVertexArray();
GL.BindVertexArray(_vao);
_vbo = GL.GenBuffer();
GL.BindBuffer(BufferTarget.ArrayBuffer, _vbo);
GL.BufferData(BufferTarget.ArrayBuffer, vertices.Length * sizeof(float), vertices, BufferUsageHint.StaticDraw);
_ebo = GL.GenBuffer();
GL.BindBuffer(BufferTarget.ElementArrayBuffer, _ebo);
GL.BufferData(BufferTarget.ElementArrayBuffer, indices.Length * sizeof(uint), indices, BufferUsageHint.StaticDraw);
// --- Set up Vertex Attributes based on layout ---
if (layout == VertexLayout.PosColor)
{
// layout(location = 0) in shader: vec3 position
var stride = 7 * sizeof(float);
GL.VertexAttribPointer(0, 3, VertexAttribPointerType.Float, false, stride, 0);
GL.EnableVertexAttribArray(0);
// layout(location = 1) in shader: vec4 color
GL.VertexAttribPointer(1, 4, VertexAttribPointerType.Float, false, stride, 3 * sizeof(float));
GL.EnableVertexAttribArray(1);
}
else if (layout == VertexLayout.PosTex)
{
// layout(location = 0) in shader: vec3 position
var stride = 5 * sizeof(float);
GL.VertexAttribPointer(0, 3, VertexAttribPointerType.Float, false, stride, 0);
GL.EnableVertexAttribArray(0);
// layout(location = 1) in shader: vec2 texCoord
GL.VertexAttribPointer(1, 2, VertexAttribPointerType.Float, false, stride, 3 * sizeof(float));
GL.EnableVertexAttribArray(1);
}
// ... (you could add more layouts)
GL.BindVertexArray(0);
}
// Constructor for non-indexed drawing (like your Circle)
public Mesh(float[] vertices, VertexLayout layout)
{
// Calculate vertex count based on stride
if (layout == VertexLayout.PosColor)
_vertexCount = vertices.Length / 7;
else // PosTex
_vertexCount = vertices.Length / 5;
_useIndices = false;
_ebo = 0; // No EBO
_vao = GL.GenVertexArray();
GL.BindVertexArray(_vao);
_vbo = GL.GenBuffer();
GL.BindBuffer(BufferTarget.ArrayBuffer, _vbo);
GL.BufferData(BufferTarget.ArrayBuffer, vertices.Length * sizeof(float), vertices, BufferUsageHint.StaticDraw);
// --- Set up Vertex Attributes based on layout ---
if (layout == VertexLayout.PosColor)
{
// layout(location = 0) in shader: vec3 position
var stride = 7 * sizeof(float);
GL.VertexAttribPointer(0, 3, VertexAttribPointerType.Float, false, stride, 0);
GL.EnableVertexAttribArray(0);
// layout(location = 1) in shader: vec4 color
GL.VertexAttribPointer(1, 4, VertexAttribPointerType.Float, false, stride, 3 * sizeof(float));
GL.EnableVertexAttribArray(1);
}
else if (layout == VertexLayout.PosTex)
{
// layout(location = 0) in shader: vec3 position
var stride = 5 * sizeof(float);
GL.VertexAttribPointer(0, 3, VertexAttribPointerType.Float, false, stride, 0);
GL.EnableVertexAttribArray(0);
// layout(location = 1) in shader: vec2 texCoord
GL.VertexAttribPointer(1, 2, VertexAttribPointerType.Float, false, stride, 3 * sizeof(float));
GL.EnableVertexAttribArray(1);
}
GL.BindVertexArray(0);
}
// Draw the mesh. Notice it doesn't know about shaders or matrices!
public void Draw()
{
GL.BindVertexArray(_vao);
if (_useIndices)
{
GL.DrawElements(PrimitiveType.Triangles, _vertexCount, DrawElementsType.UnsignedInt, 0);
}
else
{
// For your Circle (which used TriangleFan)
GL.DrawArrays(PrimitiveType.TriangleFan, 0, _vertexCount);
}
}
public void Dispose()
{
GL.DeleteBuffer(_vbo);
GL.DeleteBuffer(_ebo);
GL.DeleteVertexArray(_vao);
}
}