public BckANK1(UInt32 size, Stream stream) { long secptr = stream.Position - 8;//section pointer this.magic = "ANK1"; this.size = size; hdr = Header.Read(stream); //get header stream.Seek(secptr + hdr.jointanimationoffset, SeekOrigin.Begin); //go to the animations for (int i = 0; i < hdr.jointanimationcount; i++) { jointanims.Add(JointAnimation.Read(stream)); //read animations } stream.Seek(secptr + hdr.scaleoffset, SeekOrigin.Begin); //go to the scales for (int i = 0; i < hdr.scalecount; i++) { scales.Add(Data.ReadSingle(stream)); //read scales } stream.Seek(secptr + hdr.rotoffset, SeekOrigin.Begin); //go to rotations for (int i = 0; i < hdr.rotcount; i++) { rotations.Add(Data.ReadInt16(stream)); //read rotations } stream.Seek(secptr + hdr.translationoffset, SeekOrigin.Begin); //go to translations for (int i = 0; i < hdr.translationcount; i++) { translations.Add(Data.ReadSingle(stream)); //read translations } anglescale = (float)Math.Pow(2f, hdr.anglescaleexp) * (180f / 32767f); //some kind of float shenanigans stream.Seek(secptr + this.size, SeekOrigin.Begin); //seek the next section }
public static JointAnimation Read(Stream str) { JointAnimation anim = new JointAnimation(); anim.x = ComponentAnimation.Read(str); anim.y = ComponentAnimation.Read(str); anim.z = ComponentAnimation.Read(str); return(anim); }
static JointAnimation ImportAnimation(XmlNode xmlAnimation, Dictionary <string, Joint> joints) { XmlNodeList xmlChannels = xmlAnimation.SelectNodes("//channel"); List <JointAnimationChannel> channels = new List <JointAnimationChannel>(); foreach (XmlNode xmlChannel in xmlChannels) { // Target joint string target = xmlChannel.Attributes["target"].Value; string jointId = ExtractNodeIdFromTarget(target); if (!joints.ContainsKey(jointId)) { continue; //throw new ApplicationException("Animated Joint '" + jointId + "' not found"); } Joint joint = joints[jointId]; // Sampler string samplerId = xmlChannel.Attributes["source"].Value.Substring(1); XmlNode xmlSampler = xmlAnimation.SelectSingleNode("//sampler[@id='" + samplerId + "']"); if (xmlSampler == null) { throw new ApplicationException("Animation Sampler '" + samplerId + "' not found"); } var sampler = ImportSampler(xmlAnimation, xmlSampler, target); channels.Add(new JointAnimationChannel(sampler, joint)); } JointAnimation animation = new JointAnimation(channels.ToArray()); if (xmlAnimation.Attributes["id"] != null) { animation.GlobalID = xmlAnimation.Attributes["id"].Value; } if (xmlAnimation.Attributes["name"] != null) { animation.Name = xmlAnimation.Attributes["name"].Value; } if (xmlAnimation.Attributes["sid"] != null) { animation.ScopedID = xmlAnimation.Attributes["sid"].Value; } return(animation); }
/// <summary> /// Takes a list of animations each having one channel with a distinct target /// and creates a single animation of them by storing all channels of the /// input animations in one resulting animation instance. /// </summary> /// <remarks>This is necessary because some DCC tools split one "real" animation /// up into several animation tags in the collada file.</remarks> /// <param name="animations">List of animations</param> /// <returns>Merged Animation</returns> static JointAnimation MergeAnimations(IEnumerable <JointAnimation> animations) { JointAnimation animation = null; if ((from a in animations select a.Channels[0].Target).Distinct().Count() != animations.Count() || (from a in animations select a.Channels.Length).Max() > 1) { throw new Exception("Only animations with one channel each targetting distinct joints can be merged"); } var channels = (from a in animations select a.Channels[0]).ToArray(); animation = new JointAnimation(channels); return(animation); }
/// <summary> /// Takes a group of animations which affect the same joint and combines them into /// one animation with one channel. For this all transformations of each individual /// keyframe are combined. Translations are added, Scales multiplied and rotations /// multiplied as well. /// </summary> /// <param name="animations">List of animations</param> /// <returns>Combined animation</returns> static JointAnimation CombineAnimations(IEnumerable <JointAnimation> animations) { if (animations.Count() == 1) { // If there is only one animation there's no need to join return(animations.First()); } // Number of frames that have to be combined int numFrames = animations.First().NumFrames; // All animations must have the same number of frames if (!animations.All(a => a.NumFrames == numFrames)) { throw new NotImplementedException("Animations affecting the same joint must " + "have the same number of keyframes"); } var combinedKeyframes = new JointAnimationKeyFrame[numFrames]; for (int i = 0; i < numFrames; i++) { // Create a combined key frame float time = animations.First().Channels[0].Sampler.Keyframes[i].Time; Vector3 scale = new Vector3(1, 1, 1); Quaternion rotation = Quaternion.Identity; Vector3 translation = new Vector3(0, 0, 0); foreach (var add in animations.Select(anim => anim.Channels[0].Sampler.Keyframes[i])) { if (add.Scale != Vector3.One) { scale *= add.Scale; } if (add.Translation != Vector3.Zero) { translation += add.Translation; } // Single axis rotations are executed in order (as defined in the document) // Note: Not sure if this is correct if (add.Rotation != Quaternion.Identity) { rotation = add.Rotation * rotation; } } var keyframe = new JointAnimationKeyFrame(time, scale, rotation, translation); combinedKeyframes[i] = keyframe; } Joint target = animations.First().Channels[0].Target; var sampler = new JointAnimationSampler(combinedKeyframes, AnimationInterpolation.Linear); JointAnimation animation = new JointAnimation(new JointAnimationChannel[] { new JointAnimationChannel(sampler, target) }); // Names if (animations.Any(a => !String.IsNullOrEmpty(a.Name))) { animation.Name = animations.Where(a => !String.IsNullOrEmpty(a.Name)). Select(a => a.Name).Aggregate((sum, name) => sum + "+" + name); } if (animations.Any(a => !String.IsNullOrEmpty(a.GlobalID))) { animation.GlobalID = animations.Where(a => !String.IsNullOrEmpty(a.GlobalID)). Select(a => a.GlobalID).Aggregate((sum, name) => sum + "\n" + name); } return(animation); }
/// <summary> /// Takes a group of animations which affect the same joint and combines them into /// one animation with one channel. For this all transformations of each individual /// keyframe are combined. Translations are added, Scales multiplied and rotations /// multiplied as well. /// </summary> /// <param name="animations">List of animations</param> /// <returns>Combined animation</returns> static JointAnimation CombineAnimations(IEnumerable<JointAnimation> animations) { if (animations.Count() == 1) { // If there is only one animation there's no need to join return animations.First(); } // Number of frames that have to be combined int numFrames = animations.First().NumFrames; // All animations must have the same number of frames if(!animations.All(a => a.NumFrames == numFrames)) { throw new NotImplementedException("Animations affecting the same joint must " + "have the same number of keyframes"); } var combinedKeyframes = new JointAnimationKeyFrame[numFrames]; for (int i = 0; i < numFrames; i++) { // Create a combined key frame float time = animations.First().Channels[0].Sampler.Keyframes[i].Time; Vector3 scale = new Vector3(1,1,1); Quaternion rotation = Quaternion.Identity; Vector3 translation = new Vector3(0,0,0); foreach (var add in animations.Select(anim => anim.Channels[0].Sampler.Keyframes[i])) { if (add.Scale != Vector3.One) scale *= add.Scale; if (add.Translation != Vector3.Zero) translation += add.Translation; // Single axis rotations are executed in order (as defined in the document) // Note: Not sure if this is correct if (add.Rotation != Quaternion.Identity) rotation = add.Rotation * rotation; } var keyframe = new JointAnimationKeyFrame(time, scale, rotation, translation); combinedKeyframes[i] = keyframe; } Joint target = animations.First().Channels[0].Target; var sampler = new JointAnimationSampler(combinedKeyframes, AnimationInterpolation.Linear); JointAnimation animation = new JointAnimation(new JointAnimationChannel[] { new JointAnimationChannel(sampler, target) }); // Names if (animations.Any(a => !String.IsNullOrEmpty(a.Name))) { animation.Name = animations.Where(a => !String.IsNullOrEmpty(a.Name)). Select(a => a.Name).Aggregate((sum, name) => sum + "+" + name); } if (animations.Any(a => !String.IsNullOrEmpty(a.GlobalID))) { animation.GlobalID = animations.Where(a => !String.IsNullOrEmpty(a.GlobalID)). Select(a => a.GlobalID).Aggregate((sum, name) => sum + "\n" + name); } return animation; }
/// <summary> /// Takes a list of animations each having one channel with a distinct target /// and creates a single animation of them by storing all channels of the /// input animations in one resulting animation instance. /// </summary> /// <remarks>This is necessary because some DCC tools split one "real" animation /// up into several animation tags in the collada file.</remarks> /// <param name="animations">List of animations</param> /// <returns>Merged Animation</returns> static JointAnimation MergeAnimations(IEnumerable<JointAnimation> animations) { JointAnimation animation = null; if ((from a in animations select a.Channels[0].Target).Distinct().Count() != animations.Count() || (from a in animations select a.Channels.Length).Max() > 1) { throw new Exception("Only animations with one channel each targetting distinct joints can be merged"); } var channels = (from a in animations select a.Channels[0]).ToArray(); animation = new JointAnimation(channels); return animation; }
static JointAnimation ImportAnimation(XmlNode xmlAnimation, Dictionary<string,Joint> joints) { XmlNodeList xmlChannels = xmlAnimation.SelectNodes("//channel"); List<JointAnimationChannel> channels = new List<JointAnimationChannel>(); foreach (XmlNode xmlChannel in xmlChannels) { // Target joint string target = xmlChannel.Attributes["target"].Value; string jointId = ExtractNodeIdFromTarget(target); if (!joints.ContainsKey(jointId)) { continue; //throw new ApplicationException("Animated Joint '" + jointId + "' not found"); } Joint joint = joints[jointId]; // Sampler string samplerId = xmlChannel.Attributes["source"].Value.Substring(1); XmlNode xmlSampler = xmlAnimation.SelectSingleNode("//sampler[@id='" + samplerId + "']"); if (xmlSampler == null) throw new ApplicationException("Animation Sampler '" + samplerId + "' not found"); var sampler = ImportSampler(xmlAnimation, xmlSampler, target); channels.Add(new JointAnimationChannel(sampler, joint)); } JointAnimation animation = new JointAnimation(channels.ToArray()); if (xmlAnimation.Attributes["id"] != null) animation.GlobalID = xmlAnimation.Attributes["id"].Value; if (xmlAnimation.Attributes["name"] != null) animation.Name = xmlAnimation.Attributes["name"].Value; if (xmlAnimation.Attributes["sid"] != null) animation.ScopedID = xmlAnimation.Attributes["sid"].Value; return animation; }