diff --git a/Diamond/Buffers/VertexDataAttribute.cs b/Diamond/Buffers/VertexDataAttribute.cs
index a12c109..dd45cef 100644
--- a/Diamond/Buffers/VertexDataAttribute.cs
+++ b/Diamond/Buffers/VertexDataAttribute.cs
@@ -2,11 +2,22 @@
namespace Diamond.Buffers
{
+ ///
+ /// Marks a struct as vertex data that can be sent to a shader attribute
+ ///
[AttributeUsage(AttributeTargets.Struct, Inherited = false, AllowMultiple = false)]
public sealed class VertexDataAttribute : Attribute
{
+ ///
+ /// The pointer divisor for this type. A value of 0 indicates per-vertex, a value of 1+
+ /// indicates every n instances
+ ///
public int Divisor { get; set; } = 0;
+ ///
+ /// Mark a struct with information about how to iterate over vertex data of this type.
+ /// All fields of this struct must have [VertexPointer]
+ ///
public VertexDataAttribute()
{
}
diff --git a/Diamond/Buffers/VertexDataInfo.cs b/Diamond/Buffers/VertexDataInfo.cs
new file mode 100644
index 0000000..8e7fd7d
--- /dev/null
+++ b/Diamond/Buffers/VertexDataInfo.cs
@@ -0,0 +1,127 @@
+using System;
+using System.Collections.Generic;
+using System.Collections.ObjectModel;
+using System.Runtime.InteropServices;
+using Diamond.Shaders;
+using OpenTK.Graphics.OpenGL4;
+
+namespace Diamond.Buffers
+{
+ ///
+ /// Get vertex pointer information about a struct to infer how to point shader attributes to it
+ ///
+ public class VertexDataInfo
+ {
+ ///
+ /// All shader attributes supported by this type
+ ///
+ public IReadOnlyCollection Pointers { get; }
+
+ ///
+ /// The size of this type in bytes
+ ///
+ public int Stride { get; }
+
+ ///
+ /// The pointer divisor for this type. A value of 0 indicates per-vertex, a value of 1+
+ /// indicates every n instances
+ ///
+ public readonly int Divisor;
+
+ ///
+ /// Create an info class with pre-computed values
+ ///
+ /// The type's supported attributes
+ /// The type's stride
+ /// The type's pointer divisor
+ private VertexDataInfo(IList pointers, int stride, int divisor)
+ {
+ Pointers = new ReadOnlyCollection(pointers);
+ Stride = stride;
+ Divisor = divisor;
+ }
+
+ ///
+ /// Enable the attributes associated with this type on Program.Current
+ ///
+ public void EnableVertexPointers()
+ {
+ if (Program.Current == null)
+ throw new InvalidOperationException("Cant render a mesh with no active shader.");
+
+ foreach (var attr in Pointers)
+ {
+ var loc = Program.Current.AttributeLocation(attr.Name);
+ if (!loc.HasValue)
+ continue;
+ GL.EnableVertexAttribArray((int) loc);
+ GL.VertexAttribDivisor((int) loc, Divisor);
+ }
+ }
+
+ ///
+ /// Disable the attributes associated with this type on Program.Current
+ ///
+ public void DisableVertexPointers()
+ {
+ if (Program.Current == null)
+ throw new InvalidOperationException("Cant render a mesh with no active shader.");
+
+ foreach (var attr in Pointers)
+ {
+ var loc = Program.Current.AttributeLocation(attr.Name);
+ if (!loc.HasValue)
+ continue;
+ GL.DisableVertexAttribArray((int) loc);
+ }
+ }
+
+ ///
+ /// A cache of already computed information to prevent redundant reflection calls
+ ///
+ private static readonly Dictionary attribCache =
+ new Dictionary();
+
+ ///
+ /// Get the VertexDataInfo for a particular type
+ ///
+ /// The type to analyse
+ /// The VertexDataInfo for the type, or null if the type is not supported
+ public static VertexDataInfo GetInfo() where T : struct
+ {
+ if (attribCache.ContainsKey(typeof(T))) return attribCache[typeof(T)];
+
+ var vertexDataAttributes = typeof(T).GetCustomAttributes(typeof(VertexDataAttribute), false);
+
+ // the type must have [VertexData]
+ if (vertexDataAttributes.Length != 1)
+ return null;
+
+ var vertdataattrib = (VertexDataAttribute) vertexDataAttributes[0];
+ var divisor = vertdataattrib.Divisor;
+
+
+ var attribList = new List();
+ var stride = Marshal.SizeOf();
+
+ foreach (var fieldInfo in typeof(T).GetFields())
+ {
+ var attrs = fieldInfo.GetCustomAttributes(typeof(VertexPointerAttribute), false);
+
+ // all fields must have [VertexPointer]
+ if (attrs.Length == 0)
+ return null;
+
+ var offset = (int) Marshal.OffsetOf(fieldInfo.Name);
+ foreach (var attr in attrs)
+ {
+ var vpa = (VertexPointerAttribute) attr;
+ vpa.Offset = offset;
+ attribList.Add(vpa);
+ }
+ }
+
+ return new VertexDataInfo(attribList, stride, divisor);
+ }
+ }
+}
\ No newline at end of file
diff --git a/Diamond/Buffers/VertexPointerAttribute.cs b/Diamond/Buffers/VertexPointerAttribute.cs
index 53b7dd3..04ce453 100644
--- a/Diamond/Buffers/VertexPointerAttribute.cs
+++ b/Diamond/Buffers/VertexPointerAttribute.cs
@@ -1,8 +1,4 @@
using System;
-using System.Collections.Generic;
-using System.Collections.ObjectModel;
-using System.Runtime.InteropServices;
-using Diamond.Shaders;
using OpenTK.Graphics.OpenGL4;
namespace Diamond.Buffers
@@ -40,91 +36,19 @@ namespace Diamond.Buffers
/// The offset of this attribute within each element
/// Corresponds to the offset parameter to glVertexAttribPointer
///
- public int Offset { get; set; } = 0;
+ // todo this, and other values, should be moved into a different type for use with VertexDataInfo.
+ // this class should just mark fields with their use - other types should manage binding those fields
+ public int Offset { get; internal set; } = 0;
+ ///
+ /// Mark a field with information about how to point a shader attribute to it
+ ///
+ /// The name of the attribute to point to this
+ /// The number of elements to read from this field
public VertexPointerAttribute(string name, int size)
{
Name = name;
Size = size;
}
}
-
- public class VertexDataInfo
- {
- public readonly IReadOnlyCollection Pointers;
- public readonly int Stride;
- public readonly int Divisor;
-
- private VertexDataInfo(IList pointers, int stride, int divisor)
- {
- Pointers = new ReadOnlyCollection(pointers);
- Stride = stride;
- Divisor = divisor;
- }
-
- public void EnableVertexPointers()
- {
- if (Program.Current == null)
- throw new InvalidOperationException("Cant render a mesh with no active shader.");
-
- foreach (var attr in Pointers)
- {
- var loc = Program.Current.AttributeLocation(attr.Name);
- if (!loc.HasValue)
- continue;
- GL.EnableVertexAttribArray((int) loc);
- GL.VertexAttribDivisor((int) loc, Divisor);
- }
- }
-
- public void DisableVertexPointers()
- {
- if (Program.Current == null)
- throw new InvalidOperationException("Cant render a mesh with no active shader.");
-
- foreach (var attr in Pointers)
- {
- var loc = Program.Current.AttributeLocation(attr.Name);
- if (!loc.HasValue)
- continue;
- GL.DisableVertexAttribArray((int) loc);
- }
- }
-
- private static readonly Dictionary attribCache =
- new Dictionary();
-
- public static VertexDataInfo GetInfo() where T : struct
- {
- if (attribCache.ContainsKey(typeof(T))) return attribCache[typeof(T)];
-
- var vertexDataAttributes = typeof(T).GetCustomAttributes(typeof(VertexDataAttribute), false);
-
- if (vertexDataAttributes.Length != 1)
- return null;
-
- var vertdataattrib = (VertexDataAttribute) vertexDataAttributes[0];
- var divisor = vertdataattrib.Divisor;
-
-
- var attribList = new List();
- var stride = Marshal.SizeOf();
-
- foreach (var fieldInfo in typeof(T).GetFields())
- {
- var attrs = fieldInfo.GetCustomAttributes(typeof(VertexPointerAttribute), false);
- if (attrs.Length == 0) continue;
-
- var offset = (int) Marshal.OffsetOf(fieldInfo.Name);
- foreach (var attr in attrs)
- {
- var vpa = (VertexPointerAttribute) attr;
- vpa.Offset = offset;
- attribList.Add(vpa);
- }
- }
-
- return new VertexDataInfo(attribList, stride, divisor);
- }
- }
}
\ No newline at end of file
diff --git a/Diamond/Diamond.csproj b/Diamond/Diamond.csproj
index a02a020..cfa8083 100644
--- a/Diamond/Diamond.csproj
+++ b/Diamond/Diamond.csproj
@@ -52,6 +52,7 @@
+