4 using System.Collections.Generic;
7 using SiliconStudio.Paradox.Effects.Data;
8 using SiliconStudio.Paradox.Graphics;
9 using SiliconStudio.Core;
10 using SiliconStudio.Paradox.Graphics.Data;
12 namespace SiliconStudio.
Paradox.Extensions
23 if (meshDrawDatas.Count == 0)
24 throw new ArgumentException(
"Need at least 1 MeshDrawData.",
"meshDrawDatas");
26 if (meshDrawDatas.Count == 1)
27 return meshDrawDatas[0];
30 var firstMeshDrawData = meshDrawDatas[0];
31 if (!firstMeshDrawData.IsSimple())
32 throw new InvalidOperationException(
"Can only merge simple MeshDrawData.");
34 var firstVertexBuffer = firstMeshDrawData.VertexBuffers[0];
35 var hasIndexBuffer = IsIndexed(meshDrawDatas);
36 int totalVertexCount = 0;
37 int totalIndexCount = 0;
41 for (
int i = 0; i < meshDrawDatas.Count; i++)
43 var meshDrawData = meshDrawDatas[i];
48 if (!meshDrawData.IsSimple())
49 throw new InvalidOperationException(
"Can only merge simple MeshDrawData.");
51 if (meshDrawData.VertexBuffers.Length != firstMeshDrawData.VertexBuffers.Length)
52 throw new InvalidOperationException(
"Non-matching vertex buffer declarations.");
54 if (!meshDrawData.VertexBuffers[0].Declaration.Equals(firstMeshDrawData.VertexBuffers[0].Declaration))
55 throw new InvalidOperationException(
"Non-matching vertex buffer declarations.");
59 throw new InvalidOperationException(
"Can only merge TriangleList.");
62 totalVertexCount += meshDrawData.VertexBuffers[0].Count;
65 if (meshDrawData.IndexBuffer != null)
66 totalIndexCount += meshDrawData.IndexBuffer.Count;
68 totalIndexCount += meshDrawData.VertexBuffers[0].Count;
74 var destBufferData =
new byte[firstVertexBuffer.Declaration.VertexStride * totalVertexCount];
78 firstVertexBuffer.Declaration,
80 firstVertexBuffer.Stride)};
83 fixed (byte* destBufferDataStart = &destBufferData[0])
85 var destBufferDataCurrent = destBufferDataStart;
88 var sourceBuffer = meshDrawData.VertexBuffers[0].Buffer.Value;
89 fixed (byte* sourceBufferDataStart = &sourceBuffer.Content[0])
91 Utilities.CopyMemory((IntPtr)destBufferDataCurrent, (IntPtr)sourceBufferDataStart, sourceBuffer.Content.Length);
92 destBufferDataCurrent += sourceBuffer.Content.Length;
99 var use32BitIndex = can32BitIndex && totalVertexCount > ushort.MaxValue;
102 destBufferData =
new byte[(use32BitIndex ?
sizeof(uint) :
sizeof(ushort)) * totalIndexCount];
109 fixed (byte* destBufferDataStart = &destBufferData[0])
111 var destBufferDataCurrent = destBufferDataStart;
115 var indexBuffer = meshDrawData.IndexBuffer;
116 byte[] sourceBufferContent = null;
119 if (indexBuffer != null)
121 sourceBufferContent = indexBuffer.Buffer.Value.Content;
122 is32Bit = indexBuffer.Is32Bit;
128 sourceBufferContent = CreateIntIndexBuffer(offset, meshDrawData.
IndexBuffer.
Count, sourceBufferContent, is32Bit);
130 sourceBufferContent = CreateShortIndexBuffer(offset, meshDrawData.
IndexBuffer.
Count, sourceBufferContent, is32Bit);
133 fixed (byte* sourceBufferDataStart = &sourceBufferContent[0])
135 Utilities.CopyMemory((IntPtr)destBufferDataCurrent, (IntPtr)sourceBufferDataStart,
136 sourceBufferContent.Length);
137 destBufferDataCurrent += sourceBufferContent.Length;
140 offset += meshDrawData.VertexBuffers[0].Count;
144 result.DrawCount = totalIndexCount;
148 result.DrawCount = totalVertexCount;
161 var mergingLists =
new List<List<MeshDrawData>>();
163 foreach (var meshDrawData
in meshDrawDatas)
165 if (!meshDrawData.IsSimple() || meshDrawData.PrimitiveType != PrimitiveType.TriangleList)
167 mergingLists.Add(
new List<MeshDrawData> { meshDrawData });
171 bool createNewGroup =
true;
172 var currentDecl = meshDrawData.VertexBuffers[0].Declaration;
174 foreach (var group
in mergingLists)
176 if (currentDecl.Equals(group[0].VertexBuffers[0].Declaration))
178 group.Add(meshDrawData);
179 createNewGroup =
false;
185 mergingLists.Add(
new List<MeshDrawData> { meshDrawData });
199 if (meshDrawDatas.Count == 0)
200 return new List<List<MeshDrawData>>();
202 if (meshDrawDatas.Count == 1)
203 return new List<List<MeshDrawData>> { meshDrawDatas.ToList() };
207 var mergingLists =
new List<KeyValuePair<int, List<MeshDrawData>>>();
209 var maxVerticesCount = can32BitIndex ? uint.MaxValue : ushort.MaxValue;
211 foreach (var drawData
in meshDrawDatas)
213 mergingLists = mergingLists.OrderBy(x => x.Key).Reverse().ToList();
216 var vertexCount = drawData.VertexBuffers[0].Count;
217 var insertIndex = -1;
218 for (var j = 0; j < mergingLists.Count; ++j)
220 if (mergingLists[j].Key + vertexCount <= maxVerticesCount)
229 var newList =
new List<MeshDrawData>() { drawData };
230 mergingLists.Add(
new KeyValuePair<int, List<MeshDrawData>>(vertexCount, newList));
234 var kvp = mergingLists[insertIndex];
235 kvp.Value.Add(drawData);
236 mergingLists[insertIndex] =
new KeyValuePair<int, List<MeshDrawData>>(vertexCount + kvp.Key, kvp.Value);
241 return mergingLists.Select(x => x.Value).ToList();
254 var indices =
new ushort[
count];
255 if (baseIndices == null)
257 for (var i = 0; i <
count; ++i)
259 indices[i] = (ushort)(i + offset);
264 for (var i = 0; i <
count; ++i)
267 indices[i] = (ushort)(BitConverter.ToInt32(baseIndices, 4 * i) + offset);
269 indices[i] = (ushort)(BitConverter.ToInt16(baseIndices, 2 * i) + offset);
273 var sizeOf = Utilities.SizeOf(indices);
274 var buffer =
new byte[sizeOf];
275 Utilities.Write(buffer, indices, 0, indices.Length);
289 var indices =
new uint[
count];
290 if (baseIndices == null)
292 for (var i = 0; i <
count; ++i)
294 indices[i] = (uint)(i + offset);
299 for (var i = 0; i <
count; ++i)
302 indices[i] = (uint)(BitConverter.ToInt32(baseIndices, 4*i) + offset);
304 indices[i] = (uint)(BitConverter.ToInt16(baseIndices, 2 * i) + offset);
308 var sizeOf = Utilities.SizeOf(indices);
309 var buffer =
new byte[sizeOf];
310 Utilities.Write(buffer, indices, 0, indices.Length);
319 public static bool IsIndexed(IList<MeshDrawData> meshDrawDatas)
321 return meshDrawDatas.Any(drawdata => drawdata.IndexBuffer != null);
330 public static List<MeshDrawData>
GroupDrawData(
this IList<MeshDrawData> meshDrawDatas,
bool can32BitIndex)
332 var declGroups = CreateDeclarationMergeGroup(meshDrawDatas);
333 var groups = declGroups.SelectMany(x => CreateOptimizedMergeGroups(x, can32BitIndex)).ToList();
334 return groups.Select(x => MergeDrawData(x, can32BitIndex)).ToList();
static unsafe MeshDrawData MergeDrawData(IList< MeshDrawData > meshDrawDatas, bool can32BitIndex)
Transform a vertex buffer positions, normals, tangents and bitangents using the given matrix...
static List< List< MeshDrawData > > CreateOptimizedMergeGroups(IList< MeshDrawData > meshDrawDatas, bool can32BitIndex)
Create group of MeshDrawData that will be merged.
SiliconStudio.Paradox.Graphics.Data.IndexBufferBindingData IndexBuffer
Data field for SiliconStudio.Paradox.Effects.MeshDraw.IndexBuffer.
static byte[] CreateShortIndexBuffer(int offset, int count, byte[] baseIndices=null, bool is32Bit=true)
Create an short typed index buffer.
System.Int32 Count
Data field for SiliconStudio.Paradox.Graphics.IndexBufferBinding.Count.
Data type for SiliconStudio.Paradox.Graphics.IndexBufferBinding.
Data type for SiliconStudio.Paradox.Graphics.VertexBufferBinding.
static byte[] CreateIntIndexBuffer(int offset, int count, byte[] baseIndices=null, bool is32Bits=true)
Create an int typed index buffer.
Data type for SiliconStudio.Paradox.Effects.MeshDraw.
PrimitiveType
Defines how vertex data is ordered.
System.Boolean Is32Bit
Data field for SiliconStudio.Paradox.Graphics.IndexBufferBinding.Is32Bit.
static bool IsIndexed(IList< MeshDrawData > meshDrawDatas)
Check if a index buffer will be needed for this merge group.
static List< List< MeshDrawData > > CreateDeclarationMergeGroup(IList< MeshDrawData > meshDrawDatas)
Group meshes that can be merged because they have the same vertex declaration.
Content of a GPU buffer (vertex buffer, index buffer, etc...).
static List< MeshDrawData > GroupDrawData(this IList< MeshDrawData > meshDrawDatas, bool can32BitIndex)
Group the meshes.