diff --git a/Diamond/Buffers/Buffer.cs b/Diamond/Buffers/Buffer.cs
index b308dcc..3f8b037 100644
--- a/Diamond/Buffers/Buffer.cs
+++ b/Diamond/Buffers/Buffer.cs
@@ -17,7 +17,7 @@ namespace Diamond.Buffers
internal readonly BufferWrap Wrapper;
private readonly VertexDataInfo _vdi;
- private readonly int _size;
+ protected readonly int Size;
///
/// The target for this buffer; its type
@@ -38,7 +38,7 @@ namespace Diamond.Buffers
{
Wrapper = wrapper;
Name = name;
- _size = Marshal.SizeOf();
+ Size = Marshal.SizeOf();
_vdi = VertexDataInfo.GetInfo();
}
@@ -46,7 +46,7 @@ namespace Diamond.Buffers
/// Upload data to this buffer
///
/// The data to upload
- public void Data(T[] data) => Wrapper.Data(_size, data);
+ public void Data(T[] data) => Wrapper.Data(Size, data);
///
/// Upload a range of data to this buffer
@@ -54,7 +54,7 @@ namespace Diamond.Buffers
/// The range offset
/// The range length
/// The data to upload, offset and length apply to both this and the target
- public void Data(int offset, int count, T[] data) => Wrapper.SubData(_size, offset, count, data);
+ public void Data(int offset, int count, T[] data) => Wrapper.SubData(Size, offset, count, data);
///
/// Upload a range of data to this buffer
diff --git a/Diamond/Diamond.csproj b/Diamond/Diamond.csproj
index 04290a5..3a6e789 100644
--- a/Diamond/Diamond.csproj
+++ b/Diamond/Diamond.csproj
@@ -64,7 +64,7 @@
-
+
diff --git a/Diamond/Render/RenderGroup.cs b/Diamond/Render/RenderGroup.cs
index 0e2bd0f..0c250d8 100644
--- a/Diamond/Render/RenderGroup.cs
+++ b/Diamond/Render/RenderGroup.cs
@@ -13,23 +13,15 @@ namespace Diamond.Render
/// The type of data to use as Vertex information
public class RenderGroup where TInstance : struct where TVertex : struct
{
- ///
- /// The range of instance values to render
- ///
- public SubArray Instances;
///
/// The range of vertex values to render
///
- public Mesh Vertices;
+ public VertexBuffer Vertices;
///
- /// The buffer to use for instance data
+ /// The range of instance values to render
///
- public Buffer InstanceBuffer;
- ///
- /// The buffer to use for instance data
- ///
- public Buffer VertexBuffer;
+ public VertexBuffer Instance;
///
/// The program to use to render this Rendergroup
@@ -53,9 +45,6 @@ namespace Diamond.Render
{
Program.Use();
- InstanceBuffer.PointTo(Program);
- VertexBuffer.PointTo(Program);
-
Texture.Bind(0);
var texLoc = Program.UniformLocation("tex");
@@ -69,7 +58,10 @@ namespace Diamond.Render
if (projLoc.HasValue)
GL.UniformMatrix4(projLoc.Value, false, ref Camera.Projection);
- Vertices.DrawInstanced(Instances);
+ if (Instance != null)
+ Vertices.DrawInstanced(Instance);
+ else
+ Vertices.Draw();
}
}
}
\ No newline at end of file
diff --git a/Diamond/Render/VertexBuffer.cs b/Diamond/Render/VertexBuffer.cs
new file mode 100644
index 0000000..cc072d6
--- /dev/null
+++ b/Diamond/Render/VertexBuffer.cs
@@ -0,0 +1,203 @@
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Linq;
+using Diamond.Buffers;
+using Diamond.Shaders;
+using Diamond.Util;
+using NLog;
+using OpenTK;
+using OpenTK.Graphics.OpenGL4;
+using Buffer = Diamond.Buffers.Buffer;
+
+namespace Diamond.Render
+{
+ public class VertexBuffer : IDisposable where T : struct
+ {
+ private Logger Logger = LogManager.GetLogger("VertexBuffer");
+
+ public string Name { get; set; }
+ public Buffer Buffer;
+ public SubArray Vertices;
+ public PrimitiveType Primitive;
+
+ private static readonly VertexDataInfo tVdi;
+
+ static VertexBuffer()
+ {
+ tVdi = VertexDataInfo.GetInfo();
+ }
+
+ internal VertexBuffer(Buffer buffer, SubArray vertices, PrimitiveType primitive, string name)
+ {
+ Buffer = buffer;
+ Vertices = vertices;
+ Primitive = primitive;
+ Name = name;
+ }
+
+ public void Draw()
+ {
+ Buffer.PointTo(Program.Current);
+
+ tVdi.EnableVertexPointers();
+
+ GL.DrawArrays(Primitive, Vertices.Offset, Vertices.Length);
+
+ tVdi.DisableVertexPointers();
+ }
+
+ public void DrawInstanced(VertexBuffer instance) where TI : struct
+ {
+ var tiVdi = VertexBuffer.tVdi;
+
+ if (tiVdi.Divisor == 0)
+ {
+ Logger.Error("Cannot render mesh with instanced of type {0} - Divisor is 0", typeof(TI).Name);
+ return;
+ }
+
+ Buffer.PointTo(Program.Current);
+ instance.Buffer.PointTo(Program.Current);
+
+ tVdi.EnableVertexPointers();
+ tiVdi.EnableVertexPointers();
+
+ GL.DrawArraysInstancedBaseInstance(Primitive, Vertices.Offset, Vertices.Length, instance.Vertices.Length,
+ instance.Vertices.Offset);
+
+ tVdi.DisableVertexPointers();
+ tiVdi.DisableVertexPointers();
+ }
+
+ public void Dispose()
+ {
+ Buffer.Dispose();
+ }
+ }
+
+ public static class VertexBuffer
+ {
+ public static VertexBuffer[] FromArrays(T[][] arrays, PrimitiveType primitive = PrimitiveType.Triangles,
+ string name = null) where T : struct
+ {
+ var buffer = Buffer.Empty(BufferTarget.ArrayBuffer, BufferUsageHint.StaticDraw, name);
+
+ var vertices = arrays.SelectMany(x => x).ToArray();
+ buffer.Data(vertices);
+
+ var vertBuffers = new List>();
+
+ var offset = 0;
+ foreach (var array in arrays)
+ {
+ vertBuffers.Add(new VertexBuffer(
+ buffer,
+ new SubArray(vertices, offset, array.Length),
+ primitive, name));
+ offset += array.Length;
+ }
+
+ return vertBuffers.ToArray();
+ }
+
+ public static VertexBuffer[] FromArrays(IEnumerable> arrays,
+ PrimitiveType primitive = PrimitiveType.Triangles, string name = null) where T : struct =>
+ FromArrays(arrays.Select(x => x.ToArray()).ToArray(), primitive, name);
+
+ public static VertexBuffer[] FromWavefront(string file)
+ {
+ var lines = File.ReadAllLines(file);
+
+ var buffer = Buffer.Empty(BufferTarget.ArrayBuffer, BufferUsageHint.StaticDraw,
+ $"{file} buffer");
+
+ var vs = new List();
+ var vts = new List();
+ var vns = new List();
+ var faces = new List();
+ var vertices = new List();
+
+ var name = file;
+
+ var vertBuffers = new List>();
+
+ foreach (var line in lines)
+ {
+ if (line.StartsWith("#")) continue;
+
+ var items = line.Split(' ');
+
+ switch (items[0])
+ {
+ case "v":
+ var v = new Vector3(
+ float.Parse(items[1]),
+ float.Parse(items[2]),
+ float.Parse(items[3]));
+ vs.Add(v);
+ break;
+ case "vt":
+ var vt = new Vector2(
+ float.Parse(items[1]),
+ 1 - float.Parse(items[2]));
+ vts.Add(vt);
+ break;
+ case "vn":
+ var vn = new Vector3(
+ float.Parse(items[1]),
+ float.Parse(items[2]),
+ float.Parse(items[3]));
+ vns.Add(vn);
+ break;
+ case "f":
+ for (var i = 1; i < 4; i++)
+ {
+ var inds = items[i].Split('/');
+ var vi = inds[0] == "" ? Vector3.Zero : vs[int.Parse(inds[0]) - 1];
+ var vti = inds[1] == "" ? Vector2.Zero : vts[int.Parse(inds[1]) - 1];
+ var vni = inds[2] == "" ? Vector3.Zero : vns[int.Parse(inds[2]) - 1];
+ var f = new ObjVertex(vi, vti, vni);
+ faces.Add(f);
+ }
+ break;
+ case "o":
+ if (faces.Count > 0)
+ {
+ var count = vertices.Count;
+ vertices.AddRange(faces);
+ vertBuffers.Add(new VertexBuffer(
+ buffer,
+ new SubArray(vertices.ToArray(), count, faces.Count),
+ PrimitiveType.Triangles,
+ name));
+ }
+ name = items[1];
+ faces.Clear();
+ break;
+ default:
+ break;
+ }
+ }
+
+ if (faces.Count > 0)
+ {
+ var count = vertices.Count;
+ vertices.AddRange(faces);
+ vertBuffers.Add(new VertexBuffer(
+ buffer, new SubArray(vertices.ToArray(), count, faces.Count),
+ PrimitiveType.Triangles,
+ name));
+ }
+
+ var data = vertices.ToArray();
+
+ foreach (var vertexBuffer in vertBuffers)
+ vertexBuffer.Vertices.Array = data;
+
+ buffer.Data(vertices.ToArray());
+
+ return vertBuffers.ToArray();
+ }
+ }
+}
\ No newline at end of file
diff --git a/Diamond/Util/Mesh.cs b/Diamond/Util/Mesh.cs
deleted file mode 100644
index 2b81c1b..0000000
--- a/Diamond/Util/Mesh.cs
+++ /dev/null
@@ -1,146 +0,0 @@
-using System.Collections.Generic;
-using System.IO;
-using System.Linq;
-using Diamond.Buffers;
-using NLog;
-using OpenTK;
-using OpenTK.Graphics.OpenGL4;
-
-namespace Diamond.Util
-{
- public class Mesh where T : struct
- {
- private static readonly Logger Logger = LogManager.GetLogger("Mesh");
-
- public SubArray Vertices;
- public PrimitiveType Primitive;
-
- public string Name { get; set; }
-
- private static readonly VertexDataInfo tVdi;
-
- static Mesh()
- {
- tVdi = VertexDataInfo.GetInfo();
- }
-
- public Mesh(T[] vertices, PrimitiveType primitive = PrimitiveType.Triangles)
- : this(new SubArray(vertices), primitive)
- {
- }
-
- public Mesh(SubArray vertices, PrimitiveType primitive = PrimitiveType.Triangles)
- {
- Vertices = vertices;
- Primitive = primitive;
- }
-
- public void Draw()
- {
- tVdi.EnableVertexPointers();
-
- GL.DrawArrays(Primitive, Vertices.Offset, Vertices.Length);
-
- tVdi.DisableVertexPointers();
- }
-
- public void DrawInstanced(SubArray instanceArray) where TI : struct
- {
- var tiVdi = VertexDataInfo.GetInfo();
-
- if (tiVdi.Divisor == 0)
- {
- Logger.Error("Cannot render mesh with instances of type {0} - Divisor is 0", typeof(TI).Name);
- }
-
- tVdi.EnableVertexPointers();
- tiVdi.EnableVertexPointers();
-
- GL.DrawArraysInstancedBaseInstance(Primitive, Vertices.Offset, Vertices.Length, instanceArray.Length,
- instanceArray.Offset);
-
- tVdi.DisableVertexPointers();
- tiVdi.DisableVertexPointers();
- }
- }
-
- public static class Mesh
- {
- public static Mesh[] FromObj(string file, bool join = true)
- {
- var lines = File.ReadAllLines(file);
-
- var meshes = new List>();
- var name = file;
- var vs = new List();
- var vts = new List();
- var vns = new List();
- var faces = new List();
-
- foreach (var line in lines)
- {
- if (line.StartsWith("#")) continue;
-
- var items = line.Split(' ');
-
- switch (items[0])
- {
- case "v":
- var v = new Vector3(
- float.Parse(items[1]),
- float.Parse(items[2]),
- float.Parse(items[3]));
- vs.Add(v);
- break;
- case "vt":
- var vt = new Vector2(
- float.Parse(items[1]),
- 1 - float.Parse(items[2]));
- vts.Add(vt);
- break;
- case "vn":
- var vn = new Vector3(
- float.Parse(items[1]),
- float.Parse(items[2]),
- float.Parse(items[3]));
- vns.Add(vn);
- break;
- case "f":
- for (var i = 1; i < 4; i++)
- {
- var inds = items[i].Split('/');
- var vi = inds[0] == "" ? Vector3.Zero : vs[int.Parse(inds[0]) - 1];
- var vti = inds[1] == "" ? Vector2.Zero : vts[int.Parse(inds[1]) - 1];
- var vni = inds[2] == "" ? Vector3.Zero : vns[int.Parse(inds[2]) - 1];
- var f = new ObjVertex(vi, vti, vni);
- faces.Add(f);
- }
- break;
- case "o":
- if (faces.Count > 0)
- {
- meshes.Add(new Mesh(faces.ToArray()) {Name = name});
- faces.Clear();
- }
- name = items[1];
- break;
- }
- }
-
- if (faces.Count > 0)
- meshes.Add(new Mesh(faces.ToArray()) {Name = name});
-
- if (join)
- Join(meshes);
-
- return meshes.ToArray();
- }
-
- public static T[] Join(params Mesh[] meshes) where T : struct => Join((IEnumerable>) meshes);
-
- public static T[] Join(IEnumerable> meshes) where T : struct
- {
- return SubArray.Join(meshes.Select(x => x.Vertices));
- }
- }
-}
\ No newline at end of file
diff --git a/Diamond/Util/SubArray.cs b/Diamond/Util/SubArray.cs
index 327f4c1..dd10975 100644
--- a/Diamond/Util/SubArray.cs
+++ b/Diamond/Util/SubArray.cs
@@ -123,58 +123,58 @@ namespace Diamond.Util
///
public static class SubArray
{
- ///
- /// Make multiple subArrays cover the same array
- ///
- /// The element type
- /// The SubArrays to join
- /// The new underlying array
- public static T[] Join(params SubArray[] subArrays) => Join((IEnumerable>) subArrays);
-
- ///
- /// Make multiple subArrays cover the same array
- ///
- /// The element type
- /// The SubArrays to join
- /// The new underlying array
- public static T[] Join(IEnumerable> subArrays)
- {
- // todo: this breaks in the case: Join(a, b); Join(b, c)
- // possibly create "multiarray" class or similar which would manage these operations
- // and prevent this case from arising
-
- var subArrList = subArrays.ToList(); // prevent multiple enumeration
-
- HashSet uniqueArrays = new HashSet();
- foreach (var subArray in subArrList)
- {
- uniqueArrays.Add(subArray.Array);
- }
-
- if (uniqueArrays.Count == 0) return new T[0];
- if (uniqueArrays.Count == 1) return uniqueArrays.ToArray()[0];
-
- var length = 0;
- var offsets = new Dictionary();
- foreach (var uniqueArray in uniqueArrays)
- {
- offsets[uniqueArray] = length;
- length += uniqueArray.Length;
- }
-
- var array = new T[length];
- foreach (var uniqueArray in uniqueArrays)
- {
- System.Array.ConstrainedCopy(uniqueArray, 0, array, offsets[uniqueArray], uniqueArray.Length);
- }
-
- foreach (var subArray in subArrList)
- {
- subArray.Offset = offsets[subArray.Array];
- subArray.Array = array;
- }
-
- return array;
- }
+// ///
+// /// Make multiple subArrays cover the same array
+// ///
+// /// The element type
+// /// The SubArrays to join
+// /// The new underlying array
+// public static T[] Join(params SubArray[] subArrays) => Join((IEnumerable>) subArrays);
+//
+// ///
+// /// Make multiple subArrays cover the same array
+// ///
+// /// The element type
+// /// The SubArrays to join
+// /// The new underlying array
+// public static T[] Join(IEnumerable> subArrays)
+// {
+// // todo: this breaks in the case: Join(a, b); Join(b, c)
+// // possibly create "multiarray" class or similar which would manage these operations
+// // and prevent this case from arising
+//
+// var subArrList = subArrays.ToList(); // prevent multiple enumeration
+//
+// HashSet uniqueArrays = new HashSet();
+// foreach (var subArray in subArrList)
+// {
+// uniqueArrays.Add(subArray.Array);
+// }
+//
+// if (uniqueArrays.Count == 0) return new T[0];
+// if (uniqueArrays.Count == 1) return uniqueArrays.ToArray()[0];
+//
+// var length = 0;
+// var offsets = new Dictionary();
+// foreach (var uniqueArray in uniqueArrays)
+// {
+// offsets[uniqueArray] = length;
+// length += uniqueArray.Length;
+// }
+//
+// var array = new T[length];
+// foreach (var uniqueArray in uniqueArrays)
+// {
+// System.Array.ConstrainedCopy(uniqueArray, 0, array, offsets[uniqueArray], uniqueArray.Length);
+// }
+//
+// foreach (var subArray in subArrList)
+// {
+// subArray.Offset = offsets[subArray.Array];
+// subArray.Array = array;
+// }
+//
+// return array;
+// }
}
}
\ No newline at end of file
diff --git a/hexworld/HexRender.cs b/hexworld/HexRender.cs
index 2e75920..02fe5d1 100644
--- a/hexworld/HexRender.cs
+++ b/hexworld/HexRender.cs
@@ -1,4 +1,5 @@
using System;
+using System.Collections.Generic;
using System.IO;
using System.Linq;
using Diamond.Buffers;
@@ -43,10 +44,10 @@ namespace hexworld
#endregion
- private SubArray _floorTiles;
- private SubArray _doorTiles;
+ private VertexBuffer _floorTiles;
+ private VertexBuffer _doorTiles;
- private Mesh _cubeMesh;
+ private VertexBuffer _cubeMesh;
private Camera _camera;
@@ -86,34 +87,29 @@ namespace hexworld
.Select(arr => new SubArray(arr))
.ToArray();
- _doorTiles = allTiles[0];
- _floorTiles = allTiles[1];
+ var tileVbo = VertexBuffer.FromArrays(allTiles, 0, "tiles");
+
+ _doorTiles = tileVbo[0];
+ _floorTiles = tileVbo[1];
var cubeMesh = json["models"]
.Select(path => (string) path)
.Select(path => Path.Combine(dir, path))
- .Select(path => Mesh.FromObj(path, false))
+ .Select(VertexBuffer.FromWavefront)
.SelectMany(meshes => meshes)
.First(mesh => mesh.Name == "Cube");
_cubeMesh = cubeMesh;
- _tileBuffer = Buffer.FromData(SubArray.Join(_doorTiles, _floorTiles), BufferTarget.ArrayBuffer,
- BufferUsageHint.DynamicDraw, "tile");
- _meshBuffer = Buffer.FromData(cubeMesh.Vertices.ToArray(), BufferTarget.ArrayBuffer,
- BufferUsageHint.StaticDraw, "mesh");
-
_camera = new Camera();
_renderGroup = new RenderGroup()
{
Camera = _camera,
- Vertices = _cubeMesh,
- VertexBuffer = _meshBuffer,
+ Instance = _floorTiles,
Program = _texPgm,
- Texture = _grassTex,
- InstanceBuffer = _tileBuffer,
- Instances = _floorTiles
+ Vertices = _cubeMesh,
+ Texture = _grassTex
};
}