예제 #1
0
        private void AddTangentFrames(MeshContent mesh, ModelDescription modelDescription, MeshDescription meshDescription)
        {
            string textureCoordinateChannelName = VertexChannelNames.TextureCoordinate(0);
            string tangentChannelName           = VertexChannelNames.Tangent(0);
            string binormalChannelName          = VertexChannelNames.Binormal(0);

            bool normalsCalculated = false;

            for (int i = 0; i < mesh.Geometry.Count; i++)
            {
                var geometry = mesh.Geometry[i];

                // Check whether tangent frames are required.
                var submeshDescription = (meshDescription != null) ? meshDescription.GetSubmeshDescription(i) : null;
                if (submeshDescription != null && submeshDescription.GenerateTangentFrames ||
                    meshDescription != null && meshDescription.GenerateTangentFrames ||
                    modelDescription != null && modelDescription.GenerateTangentFrames)
                {
                    // Ensure that normals are set.
                    if (!normalsCalculated)
                    {
                        CalculateNormals(mesh, false);
                        normalsCalculated = true;
                    }

                    var  channels         = geometry.Vertices.Channels;
                    bool tangentsMissing  = !channels.Contains(tangentChannelName);
                    bool binormalsMissing = !channels.Contains(binormalChannelName);
                    if (tangentsMissing || binormalsMissing)
                    {
                        // Texture coordinates are required for calculating tangent frames.
                        if (!channels.Contains(textureCoordinateChannelName))
                        {
                            _context.Logger.LogWarning(
                                null, mesh.Identity,
                                "Texture coordinates missing in mesh '{0}', submesh {1}. Texture coordinates are required " +
                                "for calculating tangent frames.",
                                mesh.Name, i);

                            channels.Add <Vector2>(textureCoordinateChannelName, null);
                        }

                        CalculateTangentFrames(
                            geometry,
                            textureCoordinateChannelName,
                            tangentsMissing ? tangentChannelName : null,
                            binormalsMissing ? binormalChannelName : null);
                    }
                }
            }
        }
예제 #2
0
        public static ModelDescription Load(string sourceFileName, ContentPipelineContext context, bool createIfMissing)
        {
            if (sourceFileName == null)
            {
                throw new ArgumentNullException("sourceFileName");
            }
            if (sourceFileName.Length == 0)
            {
                throw new ArgumentException("File name must not be empty.", "sourceFileName");
            }
            if (context == null)
            {
                throw new ArgumentNullException("context");
            }

            string fileName = Path.ChangeExtension(sourceFileName, "drmdl");

            if (!File.Exists(fileName))
            {
                // Also try with extension xml, which was used before drmdl.
                fileName = Path.ChangeExtension(sourceFileName, "xml");
                if (!IsModelDescriptionFile(fileName))
                {
                    fileName = Path.ChangeExtension(sourceFileName, "drmdl");

                    if (!createIfMissing)
                    {
                        context.Logger.LogImportantMessage(
                            "The model description file \"{0}\" is missing. Using default settings.",
                            Path.GetFileName(fileName));

                        return(null);
                    }

                    // Create default model description file.
                    try
                    {
                        using (var stream = File.CreateText(fileName))
                        {
                            stream.Write(Properties.Resources.DefaultModelDescription, Path.GetFileName(sourceFileName));
                        }
                    }
                    catch (Exception exception)
                    {
                        context.Logger.LogImportantMessage(
                            "Automatic creation of model description \"{0}\" failed. Using default settings.\nException: {1}",
                            fileName, exception.ToString());

                        return(null);
                    }
                }
            }

            context.AddDependency(fileName);

            var modelDescription = new ModelDescription {
                Identity = new ContentIdentity(fileName)
            };

            XDocument document;

            try
            {
                document = XDocument.Load(fileName, LoadOptions.SetLineInfo);
            }
            catch (Exception exception)
            {
                string message = string.Format(CultureInfo.InvariantCulture, "Could not load '{0}': {1}", fileName, exception.Message);
                throw new InvalidContentException(message, modelDescription.Identity);
            }

            var modelElement = document.Root;

            if (modelElement == null || modelElement.Name != "Model")
            {
                string message = string.Format(CultureInfo.InvariantCulture, "Root element \"<Model>\" is missing in XML.");
                throw new InvalidContentException(message, modelDescription.Identity);
            }

            // Model attributes.
            modelDescription.Name                    = (string)modelElement.Attribute("Name") ?? Path.GetFileNameWithoutExtension(fileName);
            modelDescription.FileName                = (string)modelElement.Attribute("File") ?? (string)modelElement.Attribute("FileName");
            modelDescription.Importer                = (string)modelElement.Attribute("Importer");
            modelDescription.RotationX               = (float?)modelElement.Attribute("RotationX") ?? 0.0f;
            modelDescription.RotationY               = (float?)modelElement.Attribute("RotationY") ?? 0.0f;
            modelDescription.RotationZ               = (float?)modelElement.Attribute("RotationZ") ?? 0.0f;
            modelDescription.Scale                   = (float?)modelElement.Attribute("Scale") ?? 1.0f;
            modelDescription.GenerateTangentFrames   = (bool?)modelElement.Attribute("GenerateTangentFrames") ?? false;
            modelDescription.SwapWindingOrder        = (bool?)modelElement.Attribute("SwapWindingOrder") ?? false;
            modelDescription.PremultiplyVertexColors = (bool?)modelElement.Attribute("PremultiplyVertexColors") ?? true;
            modelDescription.MaxDistance             = (float?)modelElement.Attribute("MaxDistance") ?? 0.0f;

            var aabbMinimumAttribute = modelElement.Attribute("AabbMinimum");
            var aabbMaximumAttribute = modelElement.Attribute("AabbMaximum");

            if (aabbMinimumAttribute != null && aabbMaximumAttribute != null)
            {
                modelDescription.AabbEnabled = true;
                modelDescription.AabbMinimum = aabbMinimumAttribute.ToVector3(Vector3.Zero, modelDescription.Identity);
                modelDescription.AabbMaximum = aabbMaximumAttribute.ToVector3(Vector3.One, modelDescription.Identity);
            }

            // Mesh elements.
            modelDescription.Meshes = new List <MeshDescription>();
            foreach (var meshElement in modelElement.Elements("Mesh"))
            {
                var meshDescription = new MeshDescription();
                meshDescription.Name = (string)meshElement.Attribute("Name") ?? string.Empty;
                meshDescription.GenerateTangentFrames = (bool?)meshElement.Attribute("GenerateTangentFrames") ?? modelDescription.GenerateTangentFrames;
                meshDescription.MaxDistance           = (float?)meshElement.Attribute("MaxDistance") ?? modelDescription.MaxDistance;
                meshDescription.LodDistance           = (float?)meshElement.Attribute("LodDistance") ?? 0.0f;

                meshDescription.Submeshes = new List <SubmeshDescription>();
                foreach (var submeshElement in meshElement.Elements("Submesh"))
                {
                    var submeshDescription = new SubmeshDescription();
                    submeshDescription.GenerateTangentFrames = (bool?)meshElement.Attribute("GenerateTangentFrames") ?? meshDescription.GenerateTangentFrames;
                    submeshDescription.Material = (string)submeshElement.Attribute("Material");

                    meshDescription.Submeshes.Add(submeshDescription);
                }

                modelDescription.Meshes.Add(meshDescription);
            }

            // Animations element.
            var animationsElement = modelElement.Element("Animations");

            if (animationsElement != null)
            {
                var animationDescription = new AnimationDescription();
                animationDescription.MergeFiles             = (string)animationsElement.Attribute("MergeFiles");
                animationDescription.Splits                 = AnimationSplitter.ParseAnimationSplitDefinitions(animationsElement, modelDescription.Identity, context);
                animationDescription.ScaleCompression       = (float?)animationsElement.Attribute("ScaleCompression") ?? -1;
                animationDescription.RotationCompression    = (float?)animationsElement.Attribute("RotationCompression") ?? -1;
                animationDescription.TranslationCompression = (float?)animationsElement.Attribute("TranslationCompression") ?? -1;
                animationDescription.AddLoopFrame           = (bool?)animationsElement.Attribute("AddLoopFrame");

                modelDescription.Animation = animationDescription;
            }

            return(modelDescription);
        }