public MaterialCollectionContent CreateContent() { var dst = new MaterialCollectionContent(); dst._SharedTextures.AddRange(_SharedTextures); dst._Materials.AddRange(_Materials); return(dst); }
public MeshCollection CreateMeshCollection(MaterialCollectionContent srcMaterials, MeshCollectionContent srcMeshes) { // check arguments if (srcMaterials == null) { throw new ArgumentNullException(nameof(srcMaterials)); } if (srcMeshes == null) { throw new ArgumentNullException(nameof(srcMeshes)); } foreach (var srcPart in srcMeshes.Meshes.SelectMany(item => item.Parts)) { if (srcPart.MaterialIndex < 0 || srcPart.MaterialIndex >= srcMaterials.Materials.Count) { throw new ArgumentOutOfRangeException(nameof(srcMeshes), "MaterialIndex"); } } // initialize internals _TextureContent = srcMaterials.Textures; _Disposables = new GraphicsResourceTracker(); // instantiate vertex and index buffers var vertexBuffers = srcMeshes.SharedVertexBuffers .Select(item => item.CreateVertexBuffer(Device)) .ToArray(); var indexBuffers = srcMeshes.SharedIndexBuffers .Select(item => item.CreateIndexBuffer(Device)) .ToArray(); _Disposables.AddDisposables(vertexBuffers); _Disposables.AddDisposables(indexBuffers); // instantiate effects lambda // There isn't an exact match between content materials and effects, // because depending on the behaviour a MaterialContent might be used // on rigid and skinned meshes alike, so we have to create the // appropiate effect on demand. var rigidEffects = new Dictionary <MaterialContent, Effect>(); var skinnedEffects = new Dictionary <MaterialContent, Effect>(); Effect useEffect(MaterialContent srcMaterial, bool meshIsSkinned) { var dict = meshIsSkinned ? skinnedEffects : rigidEffects; if (dict.TryGetValue(srcMaterial, out Effect effect)) { return(effect); } effect = CreateEffect(srcMaterial, meshIsSkinned); if (effect == null) { throw new NullReferenceException(nameof(CreateEffect)); } if (meshIsSkinned && !(effect is IEffectBones)) { throw new InvalidCastException($"Effect must implement IEffectBones"); } dict[srcMaterial] = effect; _Disposables.AddDisposable(effect); return(effect); } // coalesce meshes var dstMeshes = new List <Mesh>(); foreach (var srcMesh in srcMeshes.Meshes) { var dstMesh = new Mesh(Device); foreach (var srcPart in srcMesh.Parts) { var srcMaterial = srcMaterials.Materials[srcPart.MaterialIndex]; var hasSkin = srcMeshes.SharedVertexBuffers[srcPart.Geometry.VertexBufferIndex].HasSkinning; var dstGeometry = MeshTriangles.CreateFrom(srcPart.Geometry, vertexBuffers, indexBuffers); dstGeometry.SetCullingStates(srcMaterial.DoubleSided); var dstPart = dstMesh.CreateMeshPart(); dstPart.Effect = useEffect(srcMaterial, hasSkin); dstPart.Blending = srcMaterial.Mode == MaterialBlendMode.Blend ? BlendState.NonPremultiplied : BlendState.Opaque; dstPart.Geometry = dstGeometry; } dstMeshes.Add(dstMesh); } return(new MeshCollection(dstMeshes.ToArray(), _Disposables.Disposables.ToArray())); }