Esempio n. 1
0
        private static void ProcessWeightsChannel(ContentProcessorContext context, string asset, GeometryContent geometry, int vertexChannelIndex, Dictionary <string, int> boneIndices, Dictionary <int, int> boneRemap)
        {
            if (boneIndices == null)
            {
                throw new InvalidContentException("Mesh has bone weights with no skeleton");
            }

            VertexChannelCollection channels             = geometry.Vertices.Channels;
            VertexChannel           channel2             = channels[vertexChannelIndex];
            VertexChannel <BoneWeightCollection> channel = channel2 as VertexChannel <BoneWeightCollection>;

            Byte4[]   outputIndices = new Byte4[channel.Count];
            Vector4[] outputWeights = new Vector4[channel.Count];
            for (int i = 0; i < channel.Count; i++)
            {
                BoneWeightCollection inputWeights = channel[i];
                ConvertVertexWeights(context, asset, inputWeights, boneIndices, outputIndices, outputWeights, i, geometry, boneRemap);
            }
            int    usageIndex = VertexChannelNames.DecodeUsageIndex(channel.Name);
            string name       = VertexChannelNames.EncodeName(VertexElementUsage.BlendIndices, usageIndex);
            string str        = VertexChannelNames.EncodeName(VertexElementUsage.BlendWeight, usageIndex);

            channels.Insert <Byte4>(vertexChannelIndex + 1, name, outputIndices);
            channels.Insert <Vector4>(vertexChannelIndex + 2, str, outputWeights);
            channels.RemoveAt(vertexChannelIndex);
        }
Esempio n. 2
0
        static void ProcessWeightsChannel(GeometryContent geometry, int vertexChannelIndex)
        {
            // create a map of Name->Index of the bones
            BoneContent skeleton = MeshHelper.FindSkeleton(geometry.Parent);
            Dictionary <string, int> boneIndices    = new Dictionary <string, int>();
            IList <BoneContent>      flattenedBones = MeshHelper.FlattenSkeleton(skeleton);

            for (int i = 0; i < flattenedBones.Count; i++)
            {
                boneIndices.Add(flattenedBones[i].Name, i);
            }

            // convert all of our bone weights into the correct indices and weight values
            VertexChannel <BoneWeightCollection> inputWeights = geometry.Vertices.Channels[vertexChannelIndex] as VertexChannel <BoneWeightCollection>;

            Vector4[] outputIndices = new Vector4[inputWeights.Count];
            Vector4[] outputWeights = new Vector4[inputWeights.Count];
            for (int i = 0; i < inputWeights.Count; i++)
            {
                ConvertWeights(inputWeights[i], boneIndices, outputIndices, outputWeights, i, geometry);
            }

            // create our new channel names
            int    usageIndex  = VertexChannelNames.DecodeUsageIndex(inputWeights.Name);
            string indicesName = VertexChannelNames.EncodeName(VertexElementUsage.BlendIndices, usageIndex);
            string weightsName = VertexChannelNames.EncodeName(VertexElementUsage.BlendWeight, usageIndex);

            // add in the index and weight channels
            geometry.Vertices.Channels.Insert(vertexChannelIndex + 1, indicesName, outputIndices);
            geometry.Vertices.Channels.Insert(vertexChannelIndex + 2, weightsName, outputWeights);

            // remove the original weights channel
            geometry.Vertices.Channels.RemoveAt(vertexChannelIndex);
        }
Esempio n. 3
0
        static void ProcessWeightsChannel(GeometryContent geometry, int vertexChannelIndex, SerializableSkeleton skeleton)
        {
            Dictionary <string, int> boneIndices = skeleton.boneIndexByName;

            // convert all of our bone weights into the correct indices and weight values
            VertexChannel <BoneWeightCollection> inputWeights = geometry.Vertices.Channels[vertexChannelIndex] as VertexChannel <BoneWeightCollection>;

            Vector4[] outputIndices = new Vector4[inputWeights.Count];
            Vector4[] outputWeights = new Vector4[inputWeights.Count];
            for (int i = 0; i < inputWeights.Count; i++)
            {
                ConvertWeights(inputWeights[i], boneIndices, outputIndices, outputWeights, i, geometry);
            }

            // create our new channel names
            int    usageIndex  = VertexChannelNames.DecodeUsageIndex(inputWeights.Name);
            string indicesName = VertexChannelNames.EncodeName(Microsoft.Xna.Framework.Graphics.VertexElementUsage.BlendIndices, usageIndex);
            string weightsName = VertexChannelNames.EncodeName(Microsoft.Xna.Framework.Graphics.VertexElementUsage.BlendWeight, usageIndex);

            // add in the index and weight channels
            geometry.Vertices.Channels.Insert(vertexChannelIndex + 1, indicesName, outputIndices);
            geometry.Vertices.Channels.Insert(vertexChannelIndex + 2, weightsName, outputWeights);

            // remove the original weights channel
            geometry.Vertices.Channels.RemoveAt(vertexChannelIndex);
        }
        private static void ProcessWeightsChannel(
            GeometryContent geometry, int vertexChannelIndex, ContentIdentity identity)
        {
            // NOTE: Portions of this code is from the XNA CPU Skinning
            // sample under Ms-PL, (c) Microsoft Corporation.

            // create a map of Name->Index of the bones
            var skeleton = MeshHelper.FindSkeleton(geometry.Parent);

            if (skeleton == null)
            {
                throw new InvalidContentException(
                          "Skeleton not found. Meshes that contain a Weights vertex channel cannot " +
                          "be processed without access to the skeleton data.",
                          identity);
            }

            var boneIndices    = new Dictionary <string, byte>();
            var flattenedBones = MeshHelper.FlattenSkeleton(skeleton);

            if (flattenedBones.Count > byte.MaxValue)
            {
                throw new NotSupportedException("The flattened skeleton contains more than 255 bones.");
            }

            for (int i = 0; i < flattenedBones.Count; i++)
            {
                boneIndices.Add(flattenedBones[i].Name, (byte)i);
            }

            var vertexChannel = geometry.Vertices.Channels[vertexChannelIndex];

            if (!(vertexChannel is VertexChannel <BoneWeightCollection> inputWeights))
            {
                throw new InvalidContentException(
                          string.Format(
                              "Vertex channel \"{0}\" is the wrong type. It has element type {1}. Type {2} is expected.",
                              vertexChannel.Name, vertexChannel.ElementType.FullName, typeof(BoneWeightCollection).FullName),
                          identity);
            }
            var outputIndices = new Byte4[inputWeights.Count];
            var outputWeights = new Vector4[inputWeights.Count];

            for (var i = 0; i < inputWeights.Count; i++)
            {
                ConvertWeights(inputWeights[i], boneIndices, outputIndices, outputWeights, i);
            }

            // create our new channel names
            var usageIndex  = VertexChannelNames.DecodeUsageIndex(inputWeights.Name);
            var indicesName = VertexChannelNames.EncodeName(VertexElementUsage.BlendIndices, usageIndex);
            var weightsName = VertexChannelNames.EncodeName(VertexElementUsage.BlendWeight, usageIndex);

            // add in the index and weight channels
            geometry.Vertices.Channels.Insert(vertexChannelIndex + 1, indicesName, outputIndices);
            geometry.Vertices.Channels.Insert(vertexChannelIndex + 2, weightsName, outputWeights);

            // remove the original weights channel
            geometry.Vertices.Channels.RemoveAt(vertexChannelIndex);
        }
        // Converts a channel of type BoneWeightCollection to two new channels:
        // Byte4 indices + Vector4 weights
        private void ProcessWeightsChannel(GeometryContent geometry, int vertexChannelIndex)
        {
            if (_skeleton == null)
            {
                // No skeleton? Remove BoneWeightCollection.
                geometry.Vertices.Channels.RemoveAt(vertexChannelIndex);
                return;
            }

            if (_skeleton.NumberOfBones > 255)
            {
                string message = String.Format(
                    CultureInfo.InvariantCulture,
                    "Too many bones in skeleton. Actual number of bones: {0}. Allowed number of bones: {1}.",
                    _skeleton.NumberOfBones, 255);
                throw new InvalidContentException(message, _rootBone.Identity);
            }

            var channels          = geometry.Vertices.Channels;
            var channel           = channels[vertexChannelIndex];
            var boneWeightChannel = channel as VertexChannel <BoneWeightCollection>;

            if (boneWeightChannel == null)
            {
                string message = String.Format(
                    CultureInfo.InvariantCulture,
                    "Vertex channel \"{0}\" has wrong content type. Actual type: {1}. Expected type: {2}.",
                    channel.Name, channel.ElementType, typeof(BoneWeightCollection));
                throw new InvalidContentException(message, geometry.Parent.Identity);
            }

            // Create two channels (Byte4 indices + Vector4 weights) from a BoneWeight channel.
            Byte4[]   boneIndices = new Byte4[boneWeightChannel.Count];
            Vector4[] boneWeights = new Vector4[boneWeightChannel.Count];
            for (int i = 0; i < boneWeightChannel.Count; i++)
            {
                // Convert bone weights for vertex i.
                var boneWeightCollection = boneWeightChannel[i];
                if (boneWeightCollection == null)
                {
                    string message = String.Format(
                        CultureInfo.InvariantCulture,
                        "NULL entry found in channel \"{0}\". Expected element type: {1}.",
                        boneWeightChannel.Name, typeof(BoneWeightCollection));
                    throw new InvalidContentException(message, geometry.Parent.Identity);
                }

                ConvertBoneWeights(boneWeightCollection, boneIndices, boneWeights, i, geometry);
            }

            // The current channel has the name "WeightsN", where N is the usage index.
            // Get the usage index.
            int usageIndex = VertexChannelNames.DecodeUsageIndex(boneWeightChannel.Name);

            // Store the converted bone information in two new channels called "BlendIndicesN"
            // and "BlendWeightsN".
            string blendIndices = VertexChannelNames.EncodeName(VertexElementUsage.BlendIndices, usageIndex);

            if (channels.Contains(blendIndices))
            {
                string message = String.Format(
                    CultureInfo.InvariantCulture,
                    "Cannot store converted blend indices for vertex channel \"{0}\", because a vertex channel called \"{1}\" already exists.",
                    boneWeightChannel.Name, blendIndices);
                throw new InvalidContentException(message, geometry.Parent.Identity);
            }

            string blendWeights = VertexChannelNames.EncodeName(VertexElementUsage.BlendWeight, usageIndex);

            if (channels.Contains(blendWeights))
            {
                string message = String.Format(
                    CultureInfo.InvariantCulture,
                    "Cannot store converted blend weights for vertex channel \"{0}\", because a vertex channel called \"{1}\" already exists.",
                    boneWeightChannel.Name, blendWeights);
                throw new InvalidContentException(message, geometry.Parent.Identity);
            }

            // Insert the new channels after "WeightsN" and remove "WeightsN".
            channels.Insert(vertexChannelIndex + 1, blendIndices, boneIndices);
            channels.Insert(vertexChannelIndex + 2, blendWeights, boneWeights);
            channels.RemoveAt(vertexChannelIndex);
        }