Skip to content

Commit bd95d50

Browse files
committed
Add MeshBuilder class to build MeshData components
1 parent fcfb5c5 commit bd95d50

File tree

4 files changed

+96
-15
lines changed

4 files changed

+96
-15
lines changed

Engine/Buffers/VertexBuffer.cs

Lines changed: 14 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -10,30 +10,34 @@ namespace Engine.Buffers
1010
{
1111
public class VertexBuffer<T> : Buffer, IResource where T : struct, IVertexBufferDescription
1212
{
13-
private readonly T[] _vertexData;
13+
private readonly T[] _vertices;
1414

15-
public VertexBuffer([NotNull] IEnumerable<T> vertexData, [NotNull] ushort[] indices)
15+
public VertexBuffer([NotNull] IEnumerable<IVertexBufferDescription> vertices, [NotNull] ushort[] indices)
1616
{
17-
var vertexDataArray = vertexData as T[] ?? vertexData.ToArray();
18-
Guard.AgainstNullArgument(nameof(vertexData), vertexDataArray);
19-
if (vertexDataArray.Length == 0)
17+
var verticesArray = vertices as IVertexBufferDescription[] ?? vertices.ToArray();
18+
Guard.AgainstNullArgument(nameof(vertices), verticesArray);
19+
if (!verticesArray.All(vertex => vertex is T))
2020
{
21-
throw new ArgumentException("Given vertex data must not be empty.", nameof(vertexData));
21+
throw new ArgumentException("Given vertices must all be of same type.", nameof(vertices));
2222
}
23-
_vertexData = vertexDataArray;
23+
if (verticesArray.Length == 0)
24+
{
25+
throw new ArgumentException("Given vertices must not be empty.", nameof(vertices));
26+
}
27+
_vertices = verticesArray.Cast<T>().ToArray();
2428

2529
Indices = new IndexBuffer(indices);
2630
}
2731

28-
public VertexLayoutDescription LayoutDescription => _vertexData[0].LayoutDescription;
32+
public VertexLayoutDescription LayoutDescription => _vertices[0].LayoutDescription;
2933

3034
public IndexBuffer Indices { get; }
3135

3236
public void Initialize(ResourceFactory factory, GraphicsDevice device)
3337
{
34-
var size = (uint) (_vertexData.Length * _vertexData[0].SizeInBytes);
38+
var size = (uint) (_vertices.Length * _vertices[0].SizeInBytes);
3539
_buffer = factory.CreateBuffer(new BufferDescription(size, BufferUsage.VertexBuffer));
36-
device.UpdateBuffer(_buffer, 0, _vertexData);
40+
device.UpdateBuffer(_buffer, 0, _vertices);
3741

3842
Indices.Initialize(factory, device);
3943
}

Engine/Buffers/VertexPositionNormalColor.cs

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -16,14 +16,18 @@ public VertexPositionNormalColor(Vector3 position, Vector3 normal, Vector4 color
1616
Color = color;
1717
}
1818

19-
private static readonly VertexLayoutDescription _layoutDescription = new VertexLayoutDescription(
20-
new VertexElementDescription(nameof(Position), VertexElementSemantic.Position, VertexElementFormat.Float3),
21-
new VertexElementDescription(nameof(Normal), VertexElementSemantic.Normal, VertexElementFormat.Float3),
22-
new VertexElementDescription(nameof(Color), VertexElementSemantic.Color, VertexElementFormat.Float4));
19+
public static VertexPositionNormalColor FromVertexPositionNormal(VertexPositionNormal vertex) =>
20+
new VertexPositionNormalColor(vertex.Position, vertex.Normal, RgbaFloat.Grey.ToVector4());
2321

2422
public VertexLayoutDescription LayoutDescription => _layoutDescription;
2523

2624
// float is 4 bytes(?)
2725
public uint SizeInBytes => 40;
26+
27+
// ReSharper disable once InconsistentNaming
28+
private static readonly VertexLayoutDescription _layoutDescription = new VertexLayoutDescription(
29+
new VertexElementDescription(nameof(Position), VertexElementSemantic.Position, VertexElementFormat.Float3),
30+
new VertexElementDescription(nameof(Normal), VertexElementSemantic.Normal, VertexElementFormat.Float3),
31+
new VertexElementDescription(nameof(Color), VertexElementSemantic.Color, VertexElementFormat.Float4));
2832
}
2933
}

Engine/Components/MeshData.cs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,10 @@
11
using Engine.Buffers;
2+
using Engine.ECS;
23
using Veldrid;
34

45
namespace Engine.Components
56
{
6-
public class MeshData<T> : ECS.Component, IResource where T : struct, IVertexBufferDescription
7+
public class MeshData<T> : Component, IResource where T : struct, IVertexBufferDescription
78
{
89
public MeshData(string name, VertexBuffer<T> vertexBuffer,
910
FrontFace frontFace = FrontFace.Clockwise,

Engine/Primitives/MeshBuilder.cs

Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
using System;
2+
using System.Collections.Generic;
3+
using System.Linq;
4+
using Engine.Buffers;
5+
using Engine.Components;
6+
using JetBrains.Annotations;
7+
using LiteGuard;
8+
using Veldrid;
9+
10+
namespace Engine.Primitives
11+
{
12+
public class MeshBuilder
13+
{
14+
private IVertexBufferDescription[] _vertices;
15+
private ushort[] _indices = new ushort[0];
16+
private readonly RgbaFloat? _color;
17+
18+
public MeshBuilder(RgbaFloat? color = null)
19+
{
20+
_vertices = null;
21+
_color = color;
22+
}
23+
24+
public MeshBuilder WithVertex([NotNull] IVertexBufferDescription vertex)
25+
{
26+
Guard.AgainstNullArgument(nameof(vertex), vertex);
27+
28+
return new MeshBuilder(_color)
29+
{
30+
_vertices = _vertices.Append(vertex).ToArray(),
31+
_indices = _indices
32+
};
33+
}
34+
35+
public MeshBuilder WithVertices([NotNull] IEnumerable<IVertexBufferDescription> vertices)
36+
{
37+
var verticesArray = vertices as IVertexBufferDescription[] ?? vertices.ToArray();
38+
Guard.AgainstNullArgument(nameof(vertices), verticesArray);
39+
if (verticesArray.Length == 0)
40+
{
41+
throw new ArgumentException("Given vertex data must not be empty.", nameof(vertices));
42+
}
43+
44+
return new MeshBuilder(_color)
45+
{
46+
_vertices = _vertices,
47+
_indices = _indices
48+
};
49+
}
50+
51+
/// <summary>
52+
/// Instantiates a <see cref="MeshData{T}"/> with stored vertices and indices
53+
/// </summary>
54+
/// <param name="name">Name to give the instantiated <see cref="Engine.ECS.Component"/></param>
55+
/// <returns>Guaranteed to return an instance of <see cref="MeshData{T}"/></returns>
56+
/// <exception cref="InvalidOperationException">Zero vertices are stored</exception>
57+
public object Build(string name)
58+
{
59+
if (_vertices == null || _vertices.Length == 0)
60+
{
61+
throw new InvalidOperationException("This builder contains zero vertices");
62+
}
63+
64+
if (_color == null)
65+
return new MeshData<VertexPositionNormal>(name,
66+
new VertexBuffer<VertexPositionNormal>(_vertices, _indices));
67+
68+
return new MeshData<VertexPositionNormalColor>(name,
69+
new VertexBuffer<VertexPositionNormalColor>(_vertices, _indices));
70+
}
71+
}
72+
}

0 commit comments

Comments
 (0)