/// <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); } } }
/// <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); }