public GetBoneIndex ( string boneName ) : byte | ||
boneName | string | The name of the bone. |
return | byte |
private void CreatePaletteIndices(MeshContent mesh) { foreach (GeometryContent meshPart in mesh.Geometry) { int meshIndex = (int)mesh.OpaqueData["MeshIndex"]; BoneIndexer indexer = indexers[meshIndex]; foreach (VertexChannel channel in meshPart.Vertices.Channels) { if (channel.Name == VertexChannelNames.Weights()) { VertexChannel <BoneWeightCollection> vc = (VertexChannel <BoneWeightCollection>)channel; foreach (BoneWeightCollection boneWeights in vc) { foreach (BoneWeight weight in boneWeights) { indexer.GetBoneIndex(weight.BoneName); } } } } } }
/// <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."); } }
private SkinInfoContentCollection[] ProcessSkinInfo(ModelContent model) { SkinInfoContentCollection[] info = new SkinInfoContentCollection[model.Meshes.Count]; Dictionary <string, int> boneDict = new Dictionary <string, int>(); //if (model.Bones.Count > maximumNumberOfPCBones) //{ // throw new Exception("There are too many bones! You have " + model.Bones.Count + " and you can only have " + maximumNumberOfPCBones); //} foreach (ModelBoneContent b in model.Bones) { if (b.Name != null && !boneDict.ContainsKey(b.Name)) { boneDict.Add(b.Name, b.Index); } } for (int i = 0; i < info.Length; i++) { info[i] = new SkinInfoContentCollection(); BoneIndexer indexer = indexers[i]; ReadOnlyCollection <string> skinnedBoneNames = indexer.SkinnedBoneNames; Matrix[] absoluteTransforms = new Matrix[model.Bones.Count]; CalculateAbsoluteTransforms(model.Bones[0], absoluteTransforms); Matrix absoluteMeshTransform; if (absoluteMeshTransforms == null) { absoluteMeshTransform = absoluteTransforms[model.Meshes[i].ParentBone.Index]; } else { absoluteMeshTransform = absoluteMeshTransforms[i]; } for (int j = 0; j < skinnedBoneNames.Count; j++) { string name = skinnedBoneNames[j]; SkinInfoContent content = new SkinInfoContent(); try { content.BoneIndex = boneDict[name]; } catch (KeyNotFoundException knfe) { string error = "Could not find a bone by the name of " + name + ". This is skinned bone index " + j + "."; error += "\nThere are " + skinnedBoneNames.Count + " skinned bones:"; for (int boneIndex = 0; boneIndex < skinnedBoneNames.Count; boneIndex++) { error += "\n " + skinnedBoneNames[boneIndex]; } error += "\nThere are " + model.Bones.Count + " bones:"; foreach (ModelBoneContent b in model.Bones) { error += "\n " + b.Name; } throw new KeyNotFoundException(error); } content.PaletteIndex = indexer.GetBoneIndex(name); content.InverseBindPoseTransform = absoluteMeshTransform * Matrix.Invert(absoluteTransforms[boneDict[name]]); content.BoneName = name; info[i].Add(content); } } return(info); }