Beispiel #1
0
        private static void ConvertVertexWeights(ContentProcessorContext context, string asset, BoneWeightCollection inputWeights, Dictionary <string, int> boneIndices, Byte4[] outputIndices, Vector4[] outputWeights, int vertexIndex, GeometryContent geometry, Dictionary <int, int> boneRemap)
        {
            inputWeights.NormalizeWeights(4);
            for (int i = 0; i < inputWeights.Count; i++)
            {
                BoneWeight weight = inputWeights[i];
                if (!boneIndices.TryGetValue(weight.BoneName, out tempIndices[i]))
                {
                    string boneName = weight.BoneName.Replace("__Skeleton", "");

                    if (!boneIndices.TryGetValue(boneName, out tempIndices[i]))
                    {
                        context.Logger.LogWarning(null, new ContentIdentity(asset), "Unknown bone name: " + weight.BoneName);
                        //throw new InvalidContentException("Unknown bone name: " + weight.BoneName);
                        continue;
                    }
                }
                tempWeights[i] = weight.Weight;
                if (boneRemap != null)
                {
                    tempIndices[i] = boneRemap[tempIndices[i]];
                }
            }
            for (int j = inputWeights.Count; j < 4; j++)
            {
                tempIndices[j] = 0;
                tempWeights[j] = 0f;
            }
            outputIndices[vertexIndex] = new Byte4((float)tempIndices[0], (float)tempIndices[1], (float)tempIndices[2], (float)tempIndices[3]);
            outputWeights[vertexIndex] = new Vector4(tempWeights[0], tempWeights[1], tempWeights[2], tempWeights[3]);
        }
Beispiel #2
0
        static void ConvertWeights(BoneWeightCollection inputWeights, Dictionary <string, int> boneIndices, Vector4[] outIndices, Vector4[] outWeights, int vertexIndex, GeometryContent geometry)
        {
            // we only handle 4 weights per bone
            const int maxWeights = 4;

            // create some temp arrays to hold our values
            int[]   tempIndices = new int[maxWeights];
            float[] tempWeights = new float[maxWeights];

            // cull out any extra bones
            inputWeights.NormalizeWeights(maxWeights);

            // get our indices and weights
            for (int i = 0; i < inputWeights.Count; i++)
            {
                BoneWeight weight = inputWeights[i];

                tempIndices[i] = boneIndices[weight.BoneName];
                tempWeights[i] = weight.Weight;
            }

            // zero out any remaining spaces
            for (int i = inputWeights.Count; i < maxWeights; i++)
            {
                tempIndices[i] = 0;
                tempWeights[i] = 0;
            }

            // output the values
            outIndices[vertexIndex] = new Vector4(tempIndices[0], tempIndices[1], tempIndices[2], tempIndices[3]);
            outWeights[vertexIndex] = new Vector4(tempWeights[0], tempWeights[1], tempWeights[2], tempWeights[3]);
        }
        // Convert BoneWeightCollection to Byte4 (bone indices) and Vector4 (bone weights).
        private void ConvertBoneWeights(BoneWeightCollection boneWeightCollection, Byte4[] boneIndices, Vector4[] boneWeights, int vertexIndex, GeometryContent geometry)
        {
            // Normalize weights. (Number of weights should be MaxBonesPerVertex. Sum should be 1.)
            boneWeightCollection.NormalizeWeights(MaxBonesPerVertex);

            // Convert BoneWeights object to bone indices and bone weights.
            for (int i = 0; i < boneWeightCollection.Count; i++)
            {
                BoneWeight boneWeight = boneWeightCollection[i];
                int        boneIndex  = _skeleton.GetIndex(boneWeight.BoneName);
                if (boneIndex == -1)
                {
                    string message = String.Format(
                        CultureInfo.InvariantCulture,
                        "Vertex references unknown bone name \"{0}\".",
                        boneWeight.BoneName);
                    throw new InvalidContentException(message, geometry.Parent.Identity);
                }

                _tempIndices[i] = boneIndex;
                _tempWeights[i] = boneWeight.Weight;
            }

            // Clear unused indices/weights.
            for (int i = boneWeightCollection.Count; i < MaxBonesPerVertex; i++)
            {
                _tempIndices[i] = 0;
                _tempWeights[i] = 0f;
            }

            boneIndices[vertexIndex] = new Byte4(_tempIndices[0], _tempIndices[1], _tempIndices[2], _tempIndices[3]);
            boneWeights[vertexIndex] = new Vector4(_tempWeights[0], _tempWeights[1], _tempWeights[2], _tempWeights[3]);
        }
        // From the XNA CPU Skinning Sample under Ms-PL, (c) Microsoft Corporation
        private static void ConvertWeights(
            BoneWeightCollection weights,
            Dictionary <string, byte> boneIndices,
            Byte4[] outIndices,
            Vector4[] outWeights,
            int vertexIndex)
        {
            // we only handle 4 weights per bone
            const int maxWeights = 4;

            // create some tmp spans to hold our values
            Span <byte>  tmpIndices = stackalloc byte[maxWeights];
            Span <float> tmpWeights = stackalloc float[maxWeights];

            // cull out any extra bones
            weights.NormalizeWeights(maxWeights);

            // get our indices and weights
            for (var i = 0; i < weights.Count; i++)
            {
                var weight = weights[i];
                if (!boneIndices.ContainsKey(weight.BoneName))
                {
                    throw new Exception(string.Format(
                                            "Bone '{0}' was not found in the skeleton! Skeleton bones are: '{1}'.",
                                            weight.BoneName, string.Join("', '", boneIndices.Keys)));
                }

                tmpIndices[i] = boneIndices[weight.BoneName];
                tmpWeights[i] = weight.Weight;
            }

            // zero out any remaining spaces
            for (int i = weights.Count; i < maxWeights; i++)
            {
                tmpIndices[i] = 0;
                tmpWeights[i] = 0;
            }

            // output the values
            outIndices[vertexIndex] = new Byte4(tmpIndices[0], tmpIndices[1], tmpIndices[2], tmpIndices[3]);
            outWeights[vertexIndex] = new Vector4(tmpWeights[0], tmpWeights[1], tmpWeights[2], tmpWeights[3]);
        }
        /// <summary>
        /// Go through the vertex channels in the geometry and replace the
        /// BoneWeightCollection objects with weight and index channels.
        /// </summary>
        /// <param name="geometry">The geometry to process.</param>
        /// <param name="vertexChannelIndex">The index of the vertex channel to process.</param>
        /// <param name="context">The processor context.</param>
        protected override void ProcessVertexChannel(GeometryContent geometry, int vertexChannelIndex, ContentProcessorContext context)
        {
            bool boneCollectionsWithZeroWeights = false;

            if (geometry.Vertices.Channels[vertexChannelIndex].Name == VertexChannelNames.Weights())
            {
                int         meshIndex = (int)geometry.Parent.OpaqueData["MeshIndex"];
                BoneIndexer indexer   = indexers[meshIndex];
                // Skin channels are passed in from importers as BoneWeightCollection objects
                VertexChannel <BoneWeightCollection> vc =
                    (VertexChannel <BoneWeightCollection>)
                    geometry.Vertices.Channels[vertexChannelIndex];
                int maxBonesPerVertex = 0;
                for (int i = 0; i < vc.Count; i++)
                {
                    int count = vc[i].Count;
                    if (count > maxBonesPerVertex)
                    {
                        maxBonesPerVertex = count;
                    }
                }

                // Add weights as colors (Converts well to 4 floats)
                // and indices as packed 4byte vectors.
                Color[] weightsToAdd = new Color[vc.Count];
                Byte4[] indicesToAdd = new Byte4[vc.Count];

                // Go through the BoneWeightCollections and create a new
                // weightsToAdd and indicesToAdd array for each BoneWeightCollection.
                for (int i = 0; i < vc.Count; i++)
                {
                    BoneWeightCollection bwc = vc[i];

                    if (bwc.Count == 0)
                    {
                        boneCollectionsWithZeroWeights = true;
                        continue;
                    }

                    bwc.NormalizeWeights(4);
                    int count = bwc.Count;
                    if (count > maxBonesPerVertex)
                    {
                        maxBonesPerVertex = count;
                    }

                    // Add the appropriate bone indices based on the bone names in the
                    // BoneWeightCollection
                    Vector4 bi = new Vector4();
                    bi.X = count > 0 ? indexer.GetBoneIndex(bwc[0].BoneName) : (byte)0;
                    bi.Y = count > 1 ? indexer.GetBoneIndex(bwc[1].BoneName) : (byte)0;
                    bi.Z = count > 2 ? indexer.GetBoneIndex(bwc[2].BoneName) : (byte)0;
                    bi.W = count > 3 ? indexer.GetBoneIndex(bwc[3].BoneName) : (byte)0;


                    indicesToAdd[i] = new Byte4(bi);
                    Vector4 bw = new Vector4();
                    bw.X            = count > 0 ? bwc[0].Weight : 0;
                    bw.Y            = count > 1 ? bwc[1].Weight : 0;
                    bw.Z            = count > 2 ? bwc[2].Weight : 0;
                    bw.W            = count > 3 ? bwc[3].Weight : 0;
                    weightsToAdd[i] = new Color(bw);
                }

                // Remove the old BoneWeightCollection channel
                geometry.Vertices.Channels.Remove(vc);
                // Add the new channels
                geometry.Vertices.Channels.Add <Byte4>(VertexElementUsage.BlendIndices.ToString(), indicesToAdd);
                geometry.Vertices.Channels.Add <Color>(VertexElementUsage.BlendWeight.ToString(), weightsToAdd);
            }
            else
            {
                // No skinning info, so we let the base class process the channel
                base.ProcessVertexChannel(geometry, vertexChannelIndex, context);
            }
            if (boneCollectionsWithZeroWeights)
            {
                context.Logger.LogWarning("", geometry.Identity,
                                          "BonesWeightCollections with zero weights found in geometry.");
            }
        }
        //--------------------------------------------------------------
        //--------------------------------------------------------------
        //--------------------------------------------------------------
        //--------------------------------------------------------------
        /*
        /// <summary>
        /// Gets or sets a value indicating whether alpha premultiply of vertex color is enabled.
        /// </summary>
        /// <value>
        /// <see langword="true"/> if alpha premultiply of vertex colors is enabled; otherwise, <see langword="false"/>.
        /// </value>
        [DefaultValue(true)]
        [DisplayName("Premultiply Vertex Colors")]
        [Description("If enabled, vertex color channels are converted to premultiplied alpha format.")]
        public virtual bool PremultiplyVertexColors
        {
          get { return _premultiplyVertexColors; }
          set { _premultiplyVertexColors = value; }
        }
        private bool _premultiplyVertexColors = true;
        */
        //--------------------------------------------------------------

        #endregion Other

        #if ANIMATION

        // Convert BoneWeightCollection to Byte4 (bone indices) and Vector4 (bone weights).
        private void ConvertBoneWeights(BoneWeightCollection boneWeightCollection, Byte4[] boneIndices, Vector4[] boneWeights, int vertexIndex, GeometryContent geometry)
        {
            // Normalize weights. (Number of weights should be MaxBonesPerVertex. Sum should be 1.)
              boneWeightCollection.NormalizeWeights(MaxBonesPerVertex);

              // Convert BoneWeights object to bone indices and bone weights.
              for (int i = 0; i < boneWeightCollection.Count; i++)
              {
            BoneWeight boneWeight = boneWeightCollection[i];
            int boneIndex = _skeleton.GetIndex(boneWeight.BoneName);
            if (boneIndex == -1)
            {
              string message = String.Format(
            CultureInfo.InvariantCulture,
            "Vertex references unknown bone name \"{0}\".",
            boneWeight.BoneName);
              throw new InvalidContentException(message, geometry.Parent.Identity);
            }

            _tempIndices[i] = boneIndex;
            _tempWeights[i] = boneWeight.Weight;
              }

              // Clear unused indices/weights.
              for (int i = boneWeightCollection.Count; i < MaxBonesPerVertex; i++)
              {
            _tempIndices[i] = 0;
            _tempWeights[i] = 0f;
              }

              boneIndices[vertexIndex] = new Byte4(_tempIndices[0], _tempIndices[1], _tempIndices[2], _tempIndices[3]);
              boneWeights[vertexIndex] = new Vector4(_tempWeights[0], _tempWeights[1], _tempWeights[2], _tempWeights[3]);
        }