Files
doom-dm/Engine/Renderer/Buffer/Vertex/IVertex.cs
2024-12-04 22:35:04 +03:00

50 lines
1.7 KiB
C#

using System.Reflection;
using System.Runtime.InteropServices;
using OpenTK.Graphics.OpenGL;
namespace Engine.Renderer.Buffer.Vertex;
public interface IVertex
{
public static IOrderedEnumerable<FieldInfo> GetFields<T>() => GetFields(typeof(T));
public static IOrderedEnumerable<FieldInfo> GetFields(Type type) =>
type.GetFields(BindingFlags.Public | BindingFlags.Instance).OrderBy(f => f.MetadataToken);
public static bool IsValid(Type type)
{
if (!type.IsValueType || !type.IsAssignableTo(typeof(IVertex)))
return false;
var fields = GetFields(type);
var totalSize = 0;
foreach (var field in fields)
{
if (!field.FieldType.IsValueType)
return false;
var attribute = field.GetCustomAttribute<VertexAttribute>();
if (attribute == null)
return false;
var size = AttributeSize(attribute.Type) * attribute.ComponentCount * attribute.RepeatCount;
if (size != Marshal.SizeOf(field.FieldType))
return false;
totalSize += size;
}
return totalSize == Marshal.SizeOf(type);
}
public static int AttributeSize(VertexAttribType type) => type switch
{
VertexAttribType.Byte or VertexAttribType.UnsignedByte => sizeof(byte),
VertexAttribType.Short or VertexAttribType.UnsignedShort => sizeof(short),
VertexAttribType.Int or VertexAttribType.UnsignedInt => sizeof(int),
VertexAttribType.HalfFloat => Marshal.SizeOf<Half>(),
VertexAttribType.Float => sizeof(float),
VertexAttribType.Double => sizeof(double),
_ => 0
};
}