Esempio n. 1
0
        public MaterialCollectionContent CreateContent()
        {
            var dst = new MaterialCollectionContent();

            dst._SharedTextures.AddRange(_SharedTextures);
            dst._Materials.AddRange(_Materials);
            return(dst);
        }
Esempio n. 2
0
        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()));
        }