public static Skeleton FromCollada(node root) { var skeleton = new Skeleton(); skeleton.Bones = new List<Bone>(); skeleton.LODType = 0; skeleton.Name = root.name; skeleton.BonesBySID = new Dictionary<string, Bone>(); skeleton.BonesByID = new Dictionary<string, Bone>(); Bone.FromCollada(root, -1, skeleton.Bones, skeleton.BonesBySID, skeleton.BonesByID); return skeleton; }
private void ConformSkeleton(Skeleton skeleton, Skeleton conformToSkeleton) { skeleton.LODType = conformToSkeleton.LODType; // TODO: Tolerate missing bones? foreach (var conformBone in conformToSkeleton.Bones) { Bone inputBone = null; foreach (var bone in skeleton.Bones) { if (bone.Name == conformBone.Name) { inputBone = bone; break; } } if (inputBone == null) { string msg = String.Format( "No matching bone found for conforming bone '{1}' in skeleton '{0}'.", skeleton.Name, conformBone.Name ); throw new ExportException(msg); } // Bones must have the same parent. We check this in two steps: // 1) Either both of them are root bones (no parent index) or none of them are. if ((conformBone.ParentIndex == -1) != (inputBone.ParentIndex == -1)) { string msg = String.Format( "Cannot map non-root bones to root bone '{1}' for skeleton '{0}'.", skeleton.Name, conformBone.Name ); throw new ExportException(msg); } // 2) The name of their parent bones is the same (index may differ!) if (conformBone.ParentIndex != -1) { var conformParent = conformToSkeleton.Bones[conformBone.ParentIndex]; var inputParent = skeleton.Bones[inputBone.ParentIndex]; if (conformParent.Name != inputParent.Name) { string msg = String.Format( "Conforming parent ({1}) for bone '{2}' differs from input parent ({3}) for skeleton '{0}'.", skeleton.Name, conformParent.Name, conformBone.Name, inputParent.Name ); throw new ExportException(msg); } } // The bones match, copy relevant parameters from the conforming skeleton to the input. inputBone.InverseWorldTransform = conformBone.InverseWorldTransform; inputBone.LODError = conformBone.LODError; inputBone.Transform = conformBone.Transform; } }
public bool ImportFromCollada(animation colladaAnim, Skeleton skeleton) { Animation = colladaAnim; ImportSources(); ImportSampler(); // Avoid importing empty animations if (Transforms.Count == 0) return false; ImportChannel(skeleton); return true; }
private void GenerateDummySkeleton(Root root) { foreach (var model in root.Models) { if (model.Skeleton == null) { Utils.Info(String.Format("Generating dummy skeleton for model '{0}'", model.Name)); var skeleton = new Skeleton(); skeleton.Name = model.Name; skeleton.LODType = 0; skeleton.IsDummy = true; root.Skeletons.Add(skeleton); var bone = new Bone(); bone.Name = model.Name; bone.ParentIndex = -1; skeleton.Bones = new List<Bone> { bone }; bone.Transform = new Transform(); // TODO: Transform / IWT is not always identity on dummy bones! skeleton.UpdateInverseWorldTransforms(); model.Skeleton = skeleton; foreach (var mesh in model.MeshBindings) { if (mesh.Mesh.BoneBindings != null && mesh.Mesh.BoneBindings.Count > 0) { throw new ParsingException("Failed to generate dummy skeleton: Mesh already has bone bindings."); } var binding = new BoneBinding(); binding.BoneName = bone.Name; // TODO: Calculate bounding box! binding.OBBMin = new float[] { -10, -10, -10 }; binding.OBBMax = new float[] { 10, 10, 10 }; mesh.Mesh.BoneBindings = new List<BoneBinding> { binding }; } } } }
private void ImportChannel(Skeleton skeleton) { channel channel = null; foreach (var item in Animation.Items) { if (item is channel) { channel = item as channel; break; } } if (channel == null) throw new ParsingException("Animation " + Animation.id + " has no channel!"); var parts = channel.target.Split(new char[] { '/' }); if (parts.Length != 2) throw new ParsingException("Unsupported channel target format: " + channel.target); Bone bone = null; if (!skeleton.BonesByID.TryGetValue(parts[0], out bone)) throw new ParsingException("Animation channel references nonexistent bone: " + parts[0]); if (bone.TransformSID != parts[1]) throw new ParsingException("Animation channel references nonexistent transform or transform is not float4x4: " + channel.target); Bone = bone; }