/// <summary>
        /// Gets or creates the material resource for the given VertexStructure object.
        /// </summary>
        internal static MaterialResource GetOrCreateMaterialResource(this ResourceDictionary resourceDict, VertexStructureSurface targetSurface)
        {
            NamedOrGenericKey materialKey = targetSurface.Material;
            NamedOrGenericKey textureKey  = targetSurface.TextureKey;

            // Get the material if it is already created
            if ((!materialKey.IsEmpty) && (resourceDict.ContainsResource(materialKey)))
            {
                return(resourceDict.GetResource <MaterialResource>(materialKey));
            }

            // Generate a dynamic material key
            if (materialKey.IsEmpty)
            {
                materialKey = new NamedOrGenericKey(targetSurface.MaterialProperties.GetDynamicResourceKey());
            }

            // Get the material if it is already created
            if (resourceDict.ContainsResource(materialKey))
            {
                return(resourceDict.GetResource <MaterialResource>(materialKey));
            }

            if (textureKey.IsEmpty)
            {
                // Create a default material without any texture
                SimpleColoredMaterialResource result = resourceDict.AddResource <SimpleColoredMaterialResource>(materialKey, new SimpleColoredMaterialResource());
                result.MaterialDiffuseColor = targetSurface.MaterialProperties.DiffuseColor;
                return(result);
            }
            else
            {
                // Create texture resource if needed
                try
                {
                    if ((!resourceDict.ContainsResource(textureKey)) &&
                        (!string.IsNullOrEmpty(textureKey.NameKey)))
                    {
                        // Try to find and create the texture resource by its name
                        if (targetSurface.ResourceLink != null)
                        {
                            var textureResourceLink = targetSurface.ResourceLink.GetForAnotherFile(textureKey.NameKey);

                            resourceDict.AddResource <StandardTextureResource>(
                                textureKey,
                                new StandardTextureResource(
                                    targetSurface.ResourceLink.GetForAnotherFile(textureKey.NameKey)));
                        }
                        else if (targetSurface.ResourceSourceAssembly != null)
                        {
                            var textureResourceLink = new AssemblyResourceLink(
                                targetSurface.ResourceSourceAssembly,
                                targetSurface.ResourceSourceAssembly.GetName().Name + ".Resources.Textures",
                                textureKey.NameKey);
                            if (textureResourceLink.IsValid())
                            {
                                resourceDict.AddResource <StandardTextureResource>(
                                    textureKey,
                                    new StandardTextureResource(textureResourceLink));
                            }
                            else
                            {
                                // Unable to resolve texture
                                textureKey = NamedOrGenericKey.Empty;
                            }
                        }
                        else
                        {
                            // Unable to resolve texture
                            textureKey = NamedOrGenericKey.Empty;
                        }
                    }
                }
                catch { }

                // Create a default textured material
                if (!textureKey.IsEmpty)
                {
                    SimpleColoredMaterialResource result = resourceDict.AddResource <SimpleColoredMaterialResource>(
                        materialKey,
                        new SimpleColoredMaterialResource(textureKey));
                    result.MaterialDiffuseColor = targetSurface.MaterialProperties.DiffuseColor;
                    return(result);
                }
                else
                {
                    SimpleColoredMaterialResource result = resourceDict.AddResource <SimpleColoredMaterialResource>(
                        materialKey,
                        new SimpleColoredMaterialResource());
                    result.MaterialDiffuseColor = targetSurface.MaterialProperties.DiffuseColor;
                    return(result);
                }
            }
        }
Пример #2
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());
        }
        /// <summary>
        /// Gets or creates the material resource for the given VertexStructure object.
        /// </summary>
        internal static MaterialResource GetOrCreateMaterialResourceAndEnsureLoaded(this ResourceDictionary resourceDict, VertexStructureSurface targetSurface)
        {
            MaterialResource materialResource = GetOrCreateMaterialResource(resourceDict, targetSurface);

            if (!materialResource.IsLoaded)
            {
                materialResource.LoadResource();
            }

            return(materialResource);
        }