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); }
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); }
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); }