Fewer array copies in FromWavefront, use multiple rendergroups in hexrender
This commit is contained in:
@@ -107,96 +107,93 @@ namespace Diamond.Render
|
||||
|
||||
public static VertexBuffer<ObjVertex>[] FromWavefront(string file)
|
||||
{
|
||||
var lines = File.ReadAllLines(file);
|
||||
var lines = File.ReadAllLines(file).Where(l => !l.StartsWith("#")).Select(l => l.Split(' ')).ToArray();
|
||||
|
||||
var buffer = Buffer<ObjVertex>.Empty(BufferTarget.ArrayBuffer, BufferUsageHint.StaticDraw,
|
||||
$"{file} buffer");
|
||||
|
||||
var vs = new List<Vector3>();
|
||||
var vts = new List<Vector2>();
|
||||
var vns = new List<Vector3>();
|
||||
var faces = new List<ObjVertex>();
|
||||
var vertices = new List<ObjVertex>();
|
||||
|
||||
var name = file;
|
||||
|
||||
var vertBuffers = new List<VertexBuffer<ObjVertex>>();
|
||||
|
||||
foreach (var line in lines)
|
||||
// get all positional data
|
||||
var vs = lines
|
||||
.Where(items => items[0] == "v") // only "v" lines
|
||||
.Select(items => new Vector3( // get a vector3 from the values
|
||||
float.Parse(items[1]),
|
||||
float.Parse(items[2]),
|
||||
float.Parse(items[3])))
|
||||
.ToArray();
|
||||
|
||||
// get all uv data
|
||||
var vts = lines
|
||||
.Where(items => items[0] == "vt") // only "vt" lines
|
||||
.Select(items => new Vector2( // get a vector2 from the values
|
||||
float.Parse(items[1]),
|
||||
1 - float.Parse(items[2]))) // flip along y
|
||||
.ToArray();
|
||||
|
||||
// get all normal data
|
||||
var vns = lines
|
||||
.Where(items => items[0] == "vn") // only "vn" lines
|
||||
.Select(items => new Vector3( // get a vector3 from the values
|
||||
float.Parse(items[1]),
|
||||
float.Parse(items[2]),
|
||||
float.Parse(items[3])))
|
||||
.ToArray();
|
||||
|
||||
// get all vertex data
|
||||
var vertices = lines
|
||||
.Where(items => items[0] == "f") // only "f" liens
|
||||
.Select(items => items.Skip(1)) // skip the "f" item
|
||||
.Select(items => items // get each vertex from the triangle
|
||||
.Select(inds => inds.Split('/'))) // split items into indices
|
||||
.SelectMany(inds => inds) // collapse nested index array into array of indexes
|
||||
.Select(inds => new ObjVertex( // get vertexdata from the value data at each index
|
||||
inds[0] == "" ? Vector3.Zero : vs[int.Parse(inds[0]) - 1],
|
||||
inds[1] == "" ? Vector2.Zero : vts[int.Parse(inds[1]) - 1],
|
||||
inds[2] == "" ? Vector3.Zero : vns[int.Parse(inds[2]) - 1]))
|
||||
.ToArray();
|
||||
|
||||
buffer.Data(vertices); // upload vertex data to the buffer
|
||||
|
||||
var offset = 0; // offset of each vertexbuffer
|
||||
var count = 0; // length of each vertexbuffer
|
||||
|
||||
foreach (var items in lines.Where(items => items[0] == "o" || items[0] == "f"))
|
||||
{
|
||||
if (line.StartsWith("#")) continue;
|
||||
|
||||
var items = line.Split(' ');
|
||||
|
||||
switch (items[0])
|
||||
if (items[0] != "f")
|
||||
{
|
||||
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<ObjVertex>(
|
||||
buffer,
|
||||
new SubArray<ObjVertex>(vertices.ToArray(), count, faces.Count),
|
||||
PrimitiveType.Triangles,
|
||||
name));
|
||||
}
|
||||
name = items[1];
|
||||
faces.Clear();
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
if (count > 0)
|
||||
{
|
||||
vertBuffers.Add(new VertexBuffer<ObjVertex>(
|
||||
buffer,
|
||||
new SubArray<ObjVertex>(vertices, offset, count),
|
||||
PrimitiveType.Triangles,
|
||||
name));
|
||||
}
|
||||
|
||||
// reset for next vbo and move offset to the end of this one
|
||||
name = items[1];
|
||||
offset += count;
|
||||
count = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
count += items.Length - 1; // size of current vbo increases by that many vertices
|
||||
}
|
||||
}
|
||||
|
||||
if (faces.Count > 0)
|
||||
// at the last vbo, or only vbo.
|
||||
if (count > 0)
|
||||
{
|
||||
var count = vertices.Count;
|
||||
vertices.AddRange(faces);
|
||||
vertBuffers.Add(new VertexBuffer<ObjVertex>(
|
||||
buffer, new SubArray<ObjVertex>(vertices.ToArray(), count, faces.Count),
|
||||
buffer,
|
||||
new SubArray<ObjVertex>(vertices, offset, count),
|
||||
PrimitiveType.Triangles,
|
||||
name));
|
||||
}
|
||||
|
||||
var data = vertices.ToArray();
|
||||
|
||||
foreach (var vertexBuffer in vertBuffers)
|
||||
vertexBuffer.Vertices.Array = data;
|
||||
|
||||
buffer.Data(vertices.ToArray());
|
||||
|
||||
return vertBuffers.ToArray();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -117,64 +117,4 @@ namespace Diamond.Util
|
||||
|
||||
#endregion
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Class for static SubArray operations
|
||||
/// </summary>
|
||||
public static class SubArray
|
||||
{
|
||||
// /// <summary>
|
||||
// /// Make multiple subArrays cover the same array
|
||||
// /// </summary>
|
||||
// /// <typeparam name="T">The element type</typeparam>
|
||||
// /// <param name="subArrays">The SubArrays to join</param>
|
||||
// /// <returns>The new underlying array</returns>
|
||||
// public static T[] Join<T>(params SubArray<T>[] subArrays) => Join((IEnumerable<SubArray<T>>) subArrays);
|
||||
//
|
||||
// /// <summary>
|
||||
// /// Make multiple subArrays cover the same array
|
||||
// /// </summary>
|
||||
// /// <typeparam name="T">The element type</typeparam>
|
||||
// /// <param name="subArrays">The SubArrays to join</param>
|
||||
// /// <returns>The new underlying array</returns>
|
||||
// public static T[] Join<T>(IEnumerable<SubArray<T>> 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<T[]> uniqueArrays = new HashSet<T[]>();
|
||||
// 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<T[], int>();
|
||||
// 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;
|
||||
// }
|
||||
}
|
||||
}
|
||||
@@ -19,17 +19,16 @@ namespace hexworld
|
||||
{
|
||||
#region Fields
|
||||
|
||||
#region GLObjects
|
||||
#region Disposables
|
||||
|
||||
private Program _texPgm;
|
||||
|
||||
private Texture _doorTex;
|
||||
private Texture _grassTex;
|
||||
private Texture _stoneTex;
|
||||
|
||||
private Buffer<ObjVertex> _meshBuffer;
|
||||
private Buffer<TileData> _tileBuffer;
|
||||
|
||||
private RenderGroup<TileData, ObjVertex> _renderGroup;
|
||||
private Dictionary<string, VertexBuffer<ObjVertex>> _meshVbos;
|
||||
private VertexBuffer<TileData>[] _tileVbos;
|
||||
|
||||
protected override void OnClosed(EventArgs e)
|
||||
{
|
||||
@@ -37,17 +36,19 @@ namespace hexworld
|
||||
|
||||
_doorTex?.Dispose();
|
||||
_grassTex?.Dispose();
|
||||
_stoneTex?.Dispose();
|
||||
|
||||
_meshBuffer?.Dispose();
|
||||
_tileBuffer?.Dispose();
|
||||
foreach (var vbo in _meshVbos.Values)
|
||||
vbo?.Dispose();
|
||||
|
||||
foreach (var vbo in _tileVbos)
|
||||
vbo?.Dispose();
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
private VertexBuffer<TileData> _floorTiles;
|
||||
private VertexBuffer<TileData> _doorTiles;
|
||||
|
||||
private VertexBuffer<ObjVertex> _cubeMesh;
|
||||
private List<RenderGroup<TileData, ObjVertex>> _renderGroups;
|
||||
// private RenderGroup<TileData, ObjVertex> _renderGroup;
|
||||
|
||||
private Camera _camera;
|
||||
|
||||
@@ -72,6 +73,7 @@ namespace hexworld
|
||||
|
||||
_doorTex = Texture.FromFile("res/door.png");
|
||||
_grassTex = Texture.FromFile("res/grass.png");
|
||||
_stoneTex = Texture.FromFile("res/stone.png");
|
||||
|
||||
var dir = "res";
|
||||
|
||||
@@ -87,30 +89,38 @@ namespace hexworld
|
||||
.Select(arr => new SubArray<TileData>(arr))
|
||||
.ToArray();
|
||||
|
||||
var tileVbo = VertexBuffer.FromArrays(allTiles, 0, "tiles");
|
||||
_tileVbos = VertexBuffer.FromArrays(allTiles, 0, "tiles");
|
||||
|
||||
_doorTiles = tileVbo[0];
|
||||
_floorTiles = tileVbo[1];
|
||||
|
||||
var cubeMesh = json["models"]
|
||||
var vertexBuffers = json["models"]
|
||||
.Select(path => (string) path)
|
||||
.Select(path => Path.Combine(dir, path))
|
||||
.Select(VertexBuffer.FromWavefront)
|
||||
.SelectMany(meshes => meshes)
|
||||
.First(mesh => mesh.Name == "Cube");
|
||||
.ToArray();
|
||||
|
||||
_cubeMesh = cubeMesh;
|
||||
_meshVbos = vertexBuffers.ToDictionary(vbo => vbo.Name, vbo => vbo);
|
||||
|
||||
_camera = new Camera();
|
||||
|
||||
_renderGroup = new RenderGroup<TileData, ObjVertex>()
|
||||
_renderGroups = new List<RenderGroup<TileData, ObjVertex>>();
|
||||
|
||||
_renderGroups.Add(new RenderGroup<TileData, ObjVertex>()
|
||||
{
|
||||
Camera = _camera,
|
||||
Instance = _floorTiles,
|
||||
Vertices = _meshVbos["Cube"],
|
||||
Instance = _tileVbos[0],
|
||||
Program = _texPgm,
|
||||
Vertices = _cubeMesh,
|
||||
Texture = _grassTex
|
||||
};
|
||||
Texture = _stoneTex,
|
||||
Camera = _camera,
|
||||
});
|
||||
|
||||
_renderGroups.Add(new RenderGroup<TileData, ObjVertex>()
|
||||
{
|
||||
Vertices = _meshVbos["Cube"],
|
||||
Instance = _tileVbos[1],
|
||||
Program = _texPgm,
|
||||
Texture = _grassTex,
|
||||
Camera = _camera,
|
||||
});
|
||||
}
|
||||
|
||||
protected override void OnUpdateFrame(FrameEventArgs e)
|
||||
@@ -138,7 +148,10 @@ namespace hexworld
|
||||
GL.Enable(EnableCap.Blend);
|
||||
GL.BlendFunc(BlendingFactorSrc.SrcAlpha, BlendingFactorDest.OneMinusSrcAlpha);
|
||||
|
||||
_renderGroup.Draw();
|
||||
foreach (var renderGroup in _renderGroups)
|
||||
{
|
||||
renderGroup.Draw();
|
||||
}
|
||||
|
||||
SwapBuffers();
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user