/// <summary> /// Builds vertex and index buffers. /// </summary> /// <param name="device">The device on which to build all buffers.</param> /// <param name="structures">All structure to be loaded.</param> /// <param name="resources">The current resource dictionary</param> protected virtual LoadedStructureInfo[] BuildBuffers(EngineDevice device, VertexStructure[] structures, ResourceDictionary resources) { List <LoadedStructureInfo> result = new List <LoadedStructureInfo>(structures.Length * 2); List <StandardVertex[]> cachedVertices = new List <StandardVertex[]>(2); List <int[]> cachedIndices = new List <int[]>(6); int structuresCount = structures.Length; int actVertexCount = 0; int actIndexCount = 0; int lastFinishedVertexBufferResultIndex = -1; int lastFinishedIndexBufferResultIndex = -1; int vertexBufferID = 0; int indexBufferID = 0; // Define the action which finishes current index buffer Action actionFinishIndexBuffer = () => { // Create the vertex buffer D3D11.Buffer indexBuffer = GraphicsHelper.CreateImmutableIndexBuffer( device, cachedIndices.ToArray()); cachedIndices.Clear(); actIndexCount = 0; indexBufferID++; // Do also create index buffer for (int loop = lastFinishedIndexBufferResultIndex + 1; loop < result.Count; loop++) { result[loop].IndexBuffer = indexBuffer; } lastFinishedIndexBufferResultIndex = result.Count - 1; }; // Define the action which finishes current vertex buffer Action actionFinishVertexBuffer = () => { // Create the vertex buffer D3D11.Buffer vertexBuffer = GraphicsHelper.CreateImmutableVertexBuffer( device, cachedVertices.ToArray()); cachedVertices.Clear(); actVertexCount = 0; vertexBufferID++; // Do also finish index buffers in this case actionFinishIndexBuffer(); // Do also create index buffer for (int loop = lastFinishedVertexBufferResultIndex + 1; loop < result.Count; loop++) { result[loop].VertexBuffer = vertexBuffer; } lastFinishedVertexBufferResultIndex = result.Count - 1; }; // Load all structures into memory within a loop for (int loopStruct = 0; loopStruct < structuresCount; loopStruct++) { VertexStructure actStructure = structures[loopStruct]; if (actStructure.CountVertices == 0) { continue; } if (actStructure.CountSurfaces == 0) { continue; } // Handle vertex data StandardVertex[] vertexArray = StandardVertex.FromVertexStructure(actStructure); if (actVertexCount + vertexArray.Length > MAX_VERTEX_COUNT_PER_BUFFER) { actionFinishVertexBuffer(); } cachedVertices.Add(vertexArray); int actBaseVertex = actVertexCount; actVertexCount += vertexArray.Length; // Sort all surfaces by material List <VertexStructureSurface> surfaceList = new List <VertexStructureSurface>(actStructure.Surfaces); surfaceList.Sort((left, right) => left.MaterialProperties.GetHashCode().CompareTo(right.MaterialProperties.GetHashCode())); int surfaceCount = surfaceList.Count; for (int loopSurface = 0; loopSurface < surfaceCount; loopSurface++) { VertexStructureSurface actSurface = surfaceList[loopSurface]; if (actSurface.CountTriangles == 0) { continue; } // Handle index data int[] indexArray = actSurface.GetIndexArray(); if (actBaseVertex > 0) { for (int loopIndex = 0; loopIndex < indexArray.Length; loopIndex++) { indexArray[loopIndex] = indexArray[loopIndex] + actBaseVertex; } } if (actIndexCount + indexArray.Length > MAX_INDEX_COUNT_PER_BUFFER) { actionFinishIndexBuffer(); } cachedIndices.Add(indexArray); actIndexCount += indexArray.Length; // Get or create the material LoadedStructureInfo lastStructureInfo = result.Count > 0 ? result[result.Count - 1] : null; if ((lastStructureInfo != null) && (lastStructureInfo.IndexBuffer == null) && (actSurface.MaterialProperties.Equals(lastStructureInfo.MaterialProperties))) { LoadedStructureInfo actStructureInfo = result[result.Count - 1]; actStructureInfo.IndexCount = actStructureInfo.IndexCount + indexArray.Length; } else { MaterialResource actMaterialResource = resources.GetOrCreateMaterialResourceAndEnsureLoaded(actSurface); // Create some information about the loaded structures LoadedStructureInfo newStructureInfo = new LoadedStructureInfo(); newStructureInfo.VertexBufferID = vertexBufferID; newStructureInfo.IndexBufferID = indexBufferID; newStructureInfo.SizePerVertex = StandardVertex.Size; newStructureInfo.VertexStructure = actStructure; newStructureInfo.IndexCount = indexArray.Length; newStructureInfo.StartIndex = actIndexCount - indexArray.Length; newStructureInfo.Material = actMaterialResource; newStructureInfo.MaterialProperties = actSurface.MaterialProperties; newStructureInfo.VertexBuffer = null; newStructureInfo.IndexBuffer = null; newStructureInfo.InputLayout = newStructureInfo.Material.GenerateInputLayout( device, StandardVertex.InputElements, MaterialApplyInstancingMode.SingleObject); result.Add(newStructureInfo); } } } // Finish all remaining buffers finally if (cachedVertices.Count > 0) { actionFinishVertexBuffer(); } if (cachedIndices.Count > 0) { actionFinishIndexBuffer(); } return(result.ToArray()); }