Ejemplo n.º 1
0
            protected override void ComputeParameterHash(BinarySerializationWriter writer)
            {
                base.ComputeParameterHash(writer);

                var prefabAsset = AssetFinder.FindAssetFromProxyObject(Parameters.Prefab);

                if (prefabAsset != null)
                {
                    writer.Write(prefabAsset.Version);
                }
            }
Ejemplo n.º 2
0
            protected override Task <ResultStatus> DoCommandOverride(ICommandContext commandContext)
            {
                var contentManager = new ContentManager();

                var device = GraphicsDevice.New();

                var fallbackMaterial = Material.New(device, new MaterialDescriptor
                {
                    Attributes =
                    {
                        Diffuse      = new MaterialDiffuseMapFeature(new ComputeTextureColor()),
                        DiffuseModel = new MaterialDiffuseLambertModelFeature()
                    }
                });

                var loadSettings = new ContentManagerLoaderSettings
                {
                    ContentFilter = ContentManagerLoaderSettings.NewContentFilterByType(typeof(Mesh), typeof(Material))
                };

                IList <Entity> allEntities = new List <Entity>();

                if (Parameters.Prefab != null)
                {
                    var prefab = AssetFinder.FindAssetFromProxyObject(Parameters.Prefab)?.Asset as PrefabAsset;
                    if (prefab != null)
                    {
                        allEntities = prefab.Hierarchy.Parts.Values.Select(x => x.Entity).ToList();
                    }
                }

                var prefabModel = new Model();

                //The objective is to create 1 mesh per material/shadow params
                //1. We group by materials
                //2. Create a mesh per material (might need still more meshes if 16bit indexes or more then 32bit)

                var materials   = new Dictionary <MaterialInstance, List <EntityChunk> >();
                var loadedModel = new List <Model>();

                foreach (var subEntity in allEntities)
                {
                    var modelComponent = subEntity.Get <ModelComponent>();

                    if (modelComponent?.Model == null || (modelComponent.Skeleton != null && modelComponent.Skeleton.Nodes.Length != 1) || !modelComponent.Enabled)
                    {
                        continue;
                    }

                    var modelAsset = AssetFinder.FindAssetFromProxyObject(modelComponent.Model);
                    if (modelAsset == null)
                    {
                        continue;
                    }

                    var model = contentManager.Load <Model>(modelAsset.Location, loadSettings);
                    loadedModel.Add(model);

                    if (model == null ||
                        model.Meshes.Any(x => x.Draw.PrimitiveType != PrimitiveType.TriangleList || x.Draw.VertexBuffers == null || x.Draw.VertexBuffers.Length != 1) ||
                        model.Materials.Any(x => x.Material != null && x.Material.Passes.Any(pass => pass.HasTransparency)) ||
                        modelComponent.Materials.Values.Any(x => x.Passes.Any(pass => pass.HasTransparency))) //For now we limit only to TriangleList types and interleaved vertex buffers, also we skip transparent
                    {
                        commandContext.Logger.Info($"Skipped entity {subEntity.Name} since it's not compatible with PrefabModel.");
                        continue;
                    }

                    for (var index = 0; index < model.Materials.Count; index++)
                    {
                        var material = model.Materials[index];
                        var mat      = ExtractMaterialInstance(material, index, modelComponent, fallbackMaterial);

                        var chunk = new EntityChunk {
                            Entity = subEntity, Model = model, MaterialIndex = index
                        };

                        if (materials.TryGetValue(mat, out var entities))
                        {
                            entities.Add(chunk);
                        }
                        else
                        {
                            materials.Add(mat, new List <EntityChunk> {
                                chunk
                            });
                        }
                    }
                }

                foreach (var material in materials)
                {
                    ProcessMaterial(contentManager, material.Value, material.Key, prefabModel);
                }

                // split the meshes if necessary
                prefabModel.Meshes = SplitExtensions.SplitMeshes(prefabModel.Meshes, renderingSettings.DefaultGraphicsProfile > GraphicsProfile.Level_9_3);

                //handle boundng box/sphere
                var modelBoundingBox    = prefabModel.BoundingBox;
                var modelBoundingSphere = prefabModel.BoundingSphere;

                foreach (var mesh in prefabModel.Meshes)
                {
                    var vertexBuffers = mesh.Draw.VertexBuffers;
                    if (vertexBuffers.Length > 0)
                    {
                        // Compute local mesh bounding box (no node transformation)
                        var matrix = Matrix.Identity;
                        mesh.BoundingBox = vertexBuffers[0].ComputeBounds(ref matrix, out mesh.BoundingSphere);

                        // Compute model bounding box (includes node transformation)
                        BoundingSphere meshBoundingSphere;
                        var            meshBoundingBox = vertexBuffers[0].ComputeBounds(ref matrix, out meshBoundingSphere);
                        BoundingBox.Merge(ref modelBoundingBox, ref meshBoundingBox, out modelBoundingBox);
                        BoundingSphere.Merge(ref modelBoundingSphere, ref meshBoundingSphere, out modelBoundingSphere);
                    }

                    mesh.Draw.CompactIndexBuffer();
                }
                prefabModel.BoundingBox    = modelBoundingBox;
                prefabModel.BoundingSphere = modelBoundingSphere;

                //save
                contentManager.Save(Url, prefabModel);

                foreach (var model in loadedModel.NotNull())
                {
                    contentManager.Unload(model);
                }
                device.Dispose();

                return(Task.FromResult(ResultStatus.Successful));
            }