Ejemplo n.º 1
0
        /// <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());
        }