/// <summary>
        /// Reads skinning data
        /// </summary>
        /// <param name="description">Description</param>
        /// <param name="modelContent">Model content</param>
        /// <param name="meshName">Mesh name</param>
        /// <param name="bindShapeMatrix">Resulting bind shape matrix</param>
        /// <param name="weights">Resulting weights</param>
        /// <param name="jointNames">Resulting joints</param>
        /// <returns>Returns true if the model has skinnging data</returns>
        private static bool ReadSkinningData(DrawingDataDescription description, ModelContent modelContent, string meshName, out Matrix bindShapeMatrix, out Weight[] weights, out string[] jointNames)
        {
            bindShapeMatrix = Matrix.Identity;
            weights         = null;
            jointNames      = null;

            if (description.LoadAnimation && modelContent.Controllers != null && modelContent.SkinningInfo != null)
            {
                var cInfo = modelContent.Controllers.GetControllerForMesh(meshName);
                if (cInfo != null)
                {
                    //Apply shape matrix if controller exists but we are not loading animation info
                    bindShapeMatrix = cInfo.BindShapeMatrix;
                    weights         = cInfo.Weights;

                    //Find skeleton for controller
                    var sInfo = modelContent.SkinningInfo[cInfo.Armature];
                    jointNames = sInfo.Skeleton.GetJointNames();

                    return(true);
                }
            }

            return(false);
        }
        /// <summary>
        /// Process the vertex data
        /// </summary>
        /// <param name="description">Decription</param>
        /// <param name="geometry">Geometry</param>
        /// <param name="vertexType">Vertext type</param>
        /// <param name="vertices">Resulting vertices</param>
        /// <param name="indices">Resulting indices</param>
        private static void ProcessVertexData(DrawingDataDescription description, SubMeshContent geometry, VertexTypes vertexType, out VertexData[] vertices, out uint[] indices)
        {
            if (VertexData.IsTangent(vertexType))
            {
                geometry.ComputeTangents();
            }

            if (!description.Constraint.HasValue)
            {
                vertices = geometry.Vertices;
                indices  = geometry.Indices;

                return;
            }

            if (geometry.Indices?.Length > 0)
            {
                ComputeConstraintIndices(
                    description.Constraint.Value,
                    geometry.Vertices, geometry.Indices,
                    out vertices, out indices);
            }
            else
            {
                ComputeConstraintVertices(
                    description.Constraint.Value,
                    geometry.Vertices,
                    out vertices);

                indices = new uint[] { };
            }
        }
        /// <summary>
        /// Get vertex type from geometry
        /// </summary>
        /// <param name="description">Description</param>
        /// <param name="materials">Material dictionary</param>
        /// <param name="vertexType">Vertex type</param>
        /// <param name="isSkinned">Sets wether the current geometry has skinning data or not</param>
        /// <param name="material">Material name</param>
        /// <returns>Returns the vertex type</returns>
        private static VertexTypes GetVertexType(DrawingDataDescription description, MaterialDictionary materials, VertexTypes vertexType, bool isSkinned, string material)
        {
            var res = vertexType;

            if (isSkinned)
            {
                //Get skinned equivalent
                res = VertexData.GetSkinnedEquivalent(res);
            }

            if (!description.LoadNormalMaps)
            {
                return(res);
            }

            if (VertexData.IsTextured(res) && !VertexData.IsTangent(res))
            {
                var meshMaterial = materials[material];
                if (meshMaterial?.NormalMap != null)
                {
                    //Get tangent equivalent
                    res = VertexData.GetTangentEquivalent(res);
                }
            }

            return(res);
        }
        /// <summary>
        /// Model initialization
        /// </summary>
        /// <param name="game">Game</param>
        /// <param name="bufferManager">Buffer manager</param>
        /// <param name="modelContent">Model content</param>
        /// <param name="description">Data description</param>
        /// <returns>Returns the generated drawing data objects</returns>
        public static DrawingData Build(Game game, BufferManager bufferManager, ModelContent modelContent, DrawingDataDescription description)
        {
            DrawingData res = new DrawingData(bufferManager);

            //Animation
            if (description.LoadAnimation)
            {
                InitializeSkinningData(ref res, modelContent);
            }

            //Images
            InitializeTextures(ref res, game, modelContent, description.TextureCount);

            //Materials
            InitializeMaterials(ref res, modelContent);

            //Skins & Meshes
            InitializeGeometry(ref res, modelContent, description);

            //Update meshes into device
            InitializeMeshes(ref res, bufferManager, description.Instanced ? description.Instances : 0);

            //Lights
            InitializeLights(ref res, modelContent);

            return(res);
        }
        /// <summary>
        /// Initilize geometry
        /// </summary>
        /// <param name="drw">Drawing data</param>
        /// <param name="modelContent">Model content</param>
        /// <param name="description">Description</param>
        private static void InitializeGeometry(ref DrawingData drw, ModelContent modelContent, DrawingDataDescription description)
        {
            List <Triangle> volumeMesh = new List <Triangle>();

            foreach (string meshName in modelContent.Geometry.Keys)
            {
                //Get skinning data
                var isSkinned = ReadSkinningData(
                    description, modelContent, meshName,
                    out var bindShapeMatrix, out var weights, out var jointNames);

                //Process the mesh geometry material by material
                var dictGeometry = modelContent.Geometry[meshName];

                foreach (string material in dictGeometry.Keys)
                {
                    var geometry = dictGeometry[material];
                    if (geometry.IsVolume)
                    {
                        //If volume, store position only
                        volumeMesh.AddRange(geometry.GetTriangles());
                    }
                    else
                    {
                        //Get vertex type
                        var vertexType = GetVertexType(description, drw.Materials, geometry.VertexType, isSkinned, material);

                        //Process the vertex data
                        ProcessVertexData(
                            description, geometry, vertexType,
                            out var vertices, out var indices);

                        for (int i = 0; i < vertices.Length; i++)
                        {
                            vertices[i] = vertices[i].Transform(bindShapeMatrix);
                        }

                        //Convert the vertex data to final mesh data
                        var vertexList = VertexData.Convert(
                            vertexType,
                            vertices,
                            weights,
                            jointNames);

                        if (vertexList.Any())
                        {
                            //Create and store the mesh into the drawing data
                            Mesh nMesh = new Mesh(
                                meshName,
                                geometry.Topology,
                                vertexList.ToArray(),
                                indices);

                            drw.Meshes.Add(meshName, geometry.Material, nMesh);
                        }
                    }
                }
            }

            drw.VolumeMesh = volumeMesh.ToArray();
        }
Exemple #6
0
        /// <summary>
        /// Base model
        /// </summary>
        /// <param name="scene">Scene</param>
        /// <param name="description">Object description</param>
        protected BaseModel(Scene scene, BaseModelDescription description)
            : base(scene, description)
        {
            var desc = new DrawingDataDescription()
            {
                Instanced      = description.Instanced,
                Instances      = description.Instances,
                LoadAnimation  = description.LoadAnimation,
                LoadNormalMaps = description.LoadNormalMaps,
                TextureCount   = this.TextureCount,
                DynamicBuffers = description.Dynamic,
            };

            IEnumerable <ModelContent> geo;

            if (!string.IsNullOrEmpty(description.Content.ModelContentFilename))
            {
                string contentFile = Path.Combine(description.Content.ContentFolder, description.Content.ModelContentFilename);
                var    contentDesc = Helper.DeserializeFromFile <ModelContentDescription>(contentFile);
                var    loader      = contentDesc.GetLoader();
                geo = loader.Load(description.Content.ContentFolder, contentDesc);
            }
            else if (description.Content.ModelContentDescription != null)
            {
                var loader = description.Content.ModelContentDescription.GetLoader();
                geo = loader.Load(description.Content.ContentFolder, description.Content.ModelContentDescription);
            }
            else if (description.Content.ModelContent != null)
            {
                geo = new[] { description.Content.ModelContent };
            }
            else
            {
                throw new EngineException("No geometry found in description.");
            }

            if (geo.Count() == 1)
            {
                var iGeo = geo.First();

                if (description.Optimize)
                {
                    iGeo.Optimize();
                }

                var drawable = DrawingData.Build(this.Game, this.BufferManager, iGeo, desc);

                this.meshesByLOD.Add(LevelOfDetail.High, drawable);
            }
            else
            {
                var content = new LevelOfDetailModelContent(geo, description.Optimize);

                foreach (var lod in content.Keys)
                {
                    if (this.defaultLevelOfDetail == LevelOfDetail.None)
                    {
                        this.defaultLevelOfDetail = lod;
                    }

                    var drawable = DrawingData.Build(this.Game, this.BufferManager, content[lod], desc);

                    this.meshesByLOD.Add(lod, drawable);
                }
            }

            this.UseAnisotropicFiltering = description.UseAnisotropicFiltering;
        }