public override IEnumerable <CompilerParameters> Generate(AssetCompilerContext context, CompilerParameters baseParameters, ILogger log)
        {
            var allMaterialParameters = new List <ParameterCollection>();

            if (baseParameters.Get(MaterialAssetKeys.GenerateShader))
            {
                var assetManager = new AssetManager();
                var settings     = new AssetManagerLoaderSettings()
                {
                    ContentFilter = AssetManagerLoaderSettings.NewContentFilterByType(typeof(MaterialData)),
                };

                var hashParameters = new HashSet <ObjectId>();

                foreach (var materialAssetItem in context.Package.Assets.Where(item => item.Asset is MaterialAsset))
                {
                    var assetPath = materialAssetItem.Location.GetDirectoryAndFileName();
                    try
                    {
                        var materialData = assetManager.Load <MaterialData>(assetPath, settings);
                        if (materialData != null && materialData.Parameters != null && materialData.Parameters.Count > 0)
                        {
                            var materialParameters = new ParameterCollection();
                            AddToParameters(materialData.Parameters, materialParameters);
                            if (materialParameters.Count > 0)
                            {
                                byte[] buffer1;
                                var    id = ObjectId.FromObject(materialParameters, out buffer1);
                                if (!hashParameters.Contains(id))
                                {
                                    hashParameters.Add(id);
                                    allMaterialParameters.Add(materialParameters);
                                }
                            }
                        }
                    }
                    catch (Exception ex)
                    {
                        log.Error("Error while loading material [{0}]", ex, assetPath);
                    }
                }
            }

            if (allMaterialParameters.Count != 0)
            {
                foreach (var materialParams in allMaterialParameters)
                {
                    var compilerParameters = baseParameters.Clone();
                    materialParams.CopyTo(compilerParameters);
                    yield return(compilerParameters);
                }
            }
            else
            {
                yield return(baseParameters.Clone());
            }
        }
Ejemplo n.º 2
0
            protected override Task <ResultStatus> DoCommandOverride(ICommandContext commandContext)
            {
                var assetManager = new AssetManager();

                AssetParameters.ColliderShapes = AssetParameters.ColliderShapes.Where(x => x != null &&
                                                                                      (x.GetType() != typeof(ConvexHullColliderShapeDesc) || ((ConvexHullColliderShapeDesc)x).Model != null)).ToList();

                //pre process special types
                foreach (var convexHullDesc in
                         (from shape in AssetParameters.ColliderShapes let type = shape.GetType() where type == typeof(ConvexHullColliderShapeDesc) select shape)
                         .Cast <ConvexHullColliderShapeDesc>())
                {
                    //decompose and fill vertex data

                    var loadSettings = new AssetManagerLoaderSettings
                    {
                        ContentFilter = AssetManagerLoaderSettings.NewContentFilterByType(typeof(Mesh))
                    };

                    var modelAsset = assetManager.Load <Model>(AttachedReferenceManager.GetUrl(convexHullDesc.Model), loadSettings);
                    if (modelAsset == null)
                    {
                        continue;
                    }

                    convexHullDesc.ConvexHulls        = new List <List <List <Vector3> > >();
                    convexHullDesc.ConvexHullsIndices = new List <List <List <uint> > >();

                    commandContext.Logger.Info("Processing convex hull generation, this might take a while!");

                    var nodeTransforms = new List <Matrix>();

                    //pre-compute all node transforms, assuming nodes are ordered... see ModelViewHierarchyUpdater
                    var nodesLength = modelAsset.Hierarchy.Nodes.Length;
                    for (var i = 0; i < nodesLength; i++)
                    {
                        Matrix localMatrix;
                        TransformComponent.CreateMatrixTRS(
                            ref modelAsset.Hierarchy.Nodes[i].Transform.Translation,
                            ref modelAsset.Hierarchy.Nodes[i].Transform.Rotation,
                            ref modelAsset.Hierarchy.Nodes[i].Transform.Scaling, out localMatrix);

                        Matrix worldMatrix;
                        if (modelAsset.Hierarchy.Nodes[i].ParentIndex != -1)
                        {
                            var nodeTransform = nodeTransforms[modelAsset.Hierarchy.Nodes[i].ParentIndex];
                            Matrix.Multiply(ref localMatrix, ref nodeTransform, out worldMatrix);
                        }
                        else
                        {
                            worldMatrix = localMatrix;
                        }

                        nodeTransforms.Add(worldMatrix);
                    }

                    for (var i = 0; i < nodesLength; i++)
                    {
                        var i1 = i;
                        if (modelAsset.Meshes.All(x => x.NodeIndex != i1))
                        {
                            continue;                                                // no geometry in the node
                        }
                        var combinedVerts   = new List <float>();
                        var combinedIndices = new List <uint>();

                        var hullsList = new List <List <Vector3> >();
                        convexHullDesc.ConvexHulls.Add(hullsList);

                        var indicesList = new List <List <uint> >();
                        convexHullDesc.ConvexHullsIndices.Add(indicesList);

                        foreach (var meshData in modelAsset.Meshes.Where(x => x.NodeIndex == i1))
                        {
                            var indexOffset = (uint)combinedVerts.Count / 3;

                            var stride          = meshData.Draw.VertexBuffers[0].Declaration.VertexStride;
                            var vertexDataAsset = assetManager.Load <Graphics.Buffer>(AttachedReferenceManager.GetUrl(meshData.Draw.VertexBuffers[0].Buffer));
                            var vertexData      = vertexDataAsset.GetSerializationData().Content;
                            var vertexIndex     = meshData.Draw.VertexBuffers[0].Offset;
                            for (var v = 0; v < meshData.Draw.VertexBuffers[0].Count; v++)
                            {
                                var posMatrix = Matrix.Translation(new Vector3(BitConverter.ToSingle(vertexData, vertexIndex + 0), BitConverter.ToSingle(vertexData, vertexIndex + 4), BitConverter.ToSingle(vertexData, vertexIndex + 8)));

                                Matrix rotatedMatrix;
                                var    nodeTransform = nodeTransforms[i];
                                Matrix.Multiply(ref posMatrix, ref nodeTransform, out rotatedMatrix);

                                combinedVerts.Add(rotatedMatrix.TranslationVector.X);
                                combinedVerts.Add(rotatedMatrix.TranslationVector.Y);
                                combinedVerts.Add(rotatedMatrix.TranslationVector.Z);

                                vertexIndex += stride;
                            }

                            var indexDataAsset = assetManager.Load <Graphics.Buffer>(AttachedReferenceManager.GetUrl(meshData.Draw.IndexBuffer.Buffer));
                            var indexData      = indexDataAsset.GetSerializationData().Content;
                            var indexIndex     = meshData.Draw.IndexBuffer.Offset;
                            for (var v = 0; v < meshData.Draw.IndexBuffer.Count; v++)
                            {
                                if (meshData.Draw.IndexBuffer.Is32Bit)
                                {
                                    combinedIndices.Add(BitConverter.ToUInt32(indexData, indexIndex) + indexOffset);
                                    indexIndex += 4;
                                }
                                else
                                {
                                    combinedIndices.Add(BitConverter.ToUInt16(indexData, indexIndex) + indexOffset);
                                    indexIndex += 2;
                                }
                            }
                        }

                        var decompositionDesc = new ConvexHullMesh.DecompositionDesc
                        {
                            VertexCount   = (uint)combinedVerts.Count / 3,
                            IndicesCount  = (uint)combinedIndices.Count,
                            Vertexes      = combinedVerts.ToArray(),
                            Indices       = combinedIndices.ToArray(),
                            Depth         = convexHullDesc.Depth,
                            PosSampling   = convexHullDesc.PosSampling,
                            PosRefine     = convexHullDesc.PosRefine,
                            AngleSampling = convexHullDesc.AngleSampling,
                            AngleRefine   = convexHullDesc.AngleRefine,
                            Alpha         = convexHullDesc.Alpha,
                            Threshold     = convexHullDesc.Threshold,
                            SimpleHull    = convexHullDesc.SimpleWrap
                        };

                        lock (this)
                        {
                            convexHullMesh = new ConvexHullMesh();
                        }

                        convexHullMesh.Generate(decompositionDesc);

                        var count = convexHullMesh.Count;

                        commandContext.Logger.Info("Node generated " + count + " convex hulls");

                        var vertexCountHull = 0;

                        for (uint h = 0; h < count; h++)
                        {
                            float[] points;
                            convexHullMesh.CopyPoints(h, out points);

                            var pointList = new List <Vector3>();

                            for (var v = 0; v < points.Length; v += 3)
                            {
                                var vert = new Vector3(points[v + 0], points[v + 1], points[v + 2]);
                                pointList.Add(vert);

                                vertexCountHull++;
                            }

                            hullsList.Add(pointList);

                            uint[] indices;
                            convexHullMesh.CopyIndices(h, out indices);

                            for (var t = 0; t < indices.Length; t += 3)
                            {
                                Utilities.Swap(ref indices[t], ref indices[t + 2]);
                            }

                            var indexList = new List <uint>(indices);

                            indicesList.Add(indexList);
                        }

                        lock (this)
                        {
                            convexHullMesh.Dispose();
                            convexHullMesh = null;
                        }

                        commandContext.Logger.Info("For a total of " + vertexCountHull + " vertexes");
                    }
                }

                var runtimeShape = new PhysicsColliderShape {
                    Descriptions = AssetParameters.ColliderShapes
                };

                assetManager.Save(Url, runtimeShape);

                return(Task.FromResult(ResultStatus.Successful));
            }
        public override IEnumerable <CompilerParameters> Generate(AssetCompilerContext context, CompilerParameters baseParameters, ILogger log)
        {
            // Cache all the entity parameters once
            List <EntityParameters> entityParametersList;
            var entityParametersSet = (ConcurrentDictionary <Guid, List <EntityParameters> >)context.Properties.GetOrAdd(EntityParametersKey, key => new ConcurrentDictionary <Guid, List <EntityParameters> >());

            entityParametersList = entityParametersSet.GetOrAdd(context.Package.Id, key =>
            {
                var assetManager = new AssetManager();

                var settings = new AssetManagerLoaderSettings()
                {
                    ContentFilter = AssetManagerLoaderSettings.NewContentFilterByType(typeof(ModelData), typeof(MeshData), typeof(MaterialData), typeof(LightingConfigurationsSetData)),
                };

                var allEntityParameters = new List <EntityParameters>();
                foreach (var entityAssetItem in context.Package.Assets.Where(item => item.Asset is EntityAsset))
                {
                    var assetPath = entityAssetItem.Location.GetDirectoryAndFileName();
                    try
                    {
                        var entity = assetManager.Load <EntityData>(assetPath, settings);

                        foreach (var modelComponent in entity.Components.Select(x => x.Value).OfType <ModelComponentData>())
                        {
                            foreach (var meshData in modelComponent.Model.Value.Meshes)
                            {
                                var lightingParameters = GetLightingParameters(meshData);
                                var materialParameters = GetMeshMaterialParameters(meshData);

                                if (lightingParameters == null || lightingParameters.Count == 0)
                                {
                                    EntityParameters entityParameters;
                                    entityParameters.MaterialParameters = materialParameters;
                                    entityParameters.ModelParameters    = modelComponent.Parameters;
                                    entityParameters.MeshParameters     = meshData != null ? meshData.Parameters : null;
                                    entityParameters.LightingParameters = null;
                                    allEntityParameters.Add(entityParameters);
                                }
                                else
                                {
                                    foreach (var lightConfig in lightingParameters)
                                    {
                                        EntityParameters entityParameters;
                                        entityParameters.MaterialParameters = materialParameters;
                                        entityParameters.ModelParameters    = modelComponent.Parameters;
                                        entityParameters.MeshParameters     = meshData != null ? meshData.Parameters : null;
                                        entityParameters.LightingParameters = lightConfig;
                                        allEntityParameters.Add(entityParameters);
                                    }
                                }
                            }
                        }
                    }
                    catch (Exception ex)
                    {
                        log.Error("Error while loading model mesh [{0}]", ex, assetPath);
                    }
                }

                return(allEntityParameters);
            });

            var useMeshParameters     = baseParameters.Get(MeshKeys.UseParameters);
            var useMaterialParameters = baseParameters.Get(MaterialAssetKeys.UseParameters) && !baseParameters.Get(MaterialAssetKeys.GenerateShader);

            if ((useMeshParameters || useMaterialParameters) && entityParametersList.Count != 0)
            {
                var hashParameters = new HashSet <ObjectId>();

                foreach (var entityParameters in entityParametersList)
                {
                    // Add parameters in this order
                    // 1. Material
                    // 2. ModelComponent (Entity)
                    // 3. Mesh
                    // 4. Lighting

                    var newParameters = new ParameterCollection();
                    if (useMaterialParameters)
                    {
                        AddToParameters(entityParameters.MaterialParameters, newParameters);
                    }

                    AddToParameters(entityParameters.ModelParameters, newParameters);

                    if (useMeshParameters)
                    {
                        AddToParameters(entityParameters.MeshParameters, newParameters);
                    }

                    AddToParameters(entityParameters.LightingParameters, newParameters);

                    byte[] buffer1;
                    var    id = ObjectId.FromObject(newParameters, out buffer1);
                    if (!hashParameters.Contains(id))
                    {
                        hashParameters.Add(id);
                        var compilerParameters = baseParameters.Clone();
                        newParameters.CopyTo(compilerParameters);
                        yield return(compilerParameters);
                    }
                }
            }
            else
            {
                yield return(baseParameters.Clone());
            }
        }
Ejemplo n.º 4
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 AssetManagerLoaderSettings
                {
                    ContentFilter = AssetManagerLoaderSettings.NewContentFilterByType(typeof(Mesh), typeof(Skeleton), typeof(Material), typeof(Prefab))
                };

                Prefab prefab;

                if (AssetParameters.Prefab == null)
                {
                    prefab = new Prefab();
                }
                else
                {
                    prefab = contentManager.Load <Prefab>(AssetParameters.Prefab.Location, loadSettings);
                    if (prefab == null)
                    {
                        throw new Exception("Failed to load prefab.");
                    }
                }

                var prefabModel = new Rendering.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 validEntities = new List <Entity>();

                foreach (var rootEntity in prefab.Entities)
                {
                    //collect sub entities as well
                    var collected = IterateTree(rootEntity, subEntity => subEntity.GetChildren()).ToArray();

                    //first pass, check if compatible with prefabmodel
                    foreach (var subEntity in collected)
                    {
                        //todo for now we collect everything with a model component
                        var modelComponent = subEntity.Get <ModelComponent>();

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

                        var modelAsset = contentManager.Load <Rendering.Model>(AttachedReferenceManager.GetUrl(modelComponent.Model), loadSettings);
                        if (modelAsset == null ||
                            modelAsset.Meshes.Any(x => x.Draw.PrimitiveType != PrimitiveType.TriangleList || x.Draw.VertexBuffers == null || x.Draw.VertexBuffers.Length != 1) ||
                            modelAsset.Materials.Any(x => x.Material != null && x.Material.HasTransparency) ||
                            modelComponent.Materials.Any(x => x != null && x.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;
                        }

                        validEntities.Add(subEntity);
                    }
                }

                foreach (var subEntity in validEntities)
                {
                    var modelComponent = subEntity.Get <ModelComponent>();
                    var modelAsset     = contentManager.Load <Rendering.Model>(AttachedReferenceManager.GetUrl(modelComponent.Model), loadSettings);
                    for (var index = 0; index < modelAsset.Materials.Count; index++)
                    {
                        var material = modelAsset.Materials[index];
                        var mat      = ExtractMaterialInstance(material, index, modelComponent, fallbackMaterial);

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

                        List <EntityChunk> entities;
                        if (materials.TryGetValue(mat, out 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);

                device.Dispose();

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