protected virtual int ReduceKeyframes(Keyframe[] frames, float tolerance) { #if DEBUG if (frames == null) { throw new ArgumentNullException("frames"); } #endif int nReduced = 0; Keyframe lerp = new Keyframe(); int nFrames = frames.Length; int prevFrame = 0; Keyframe prevData = frames[0]; for (int curFrame = 1; curFrame < nFrames - 1; ++curFrame) { Keyframe curData = frames[curFrame]; int nextFrame = curFrame + 1; Keyframe nextData = frames[nextFrame]; Keyframe.Interpolate(prevData, nextData, (float)(curFrame - prevFrame) / (float)(nextFrame - prevFrame), lerp); if (lerp.DifferenceFrom(curData) < tolerance) { frames[curFrame] = null; ++nReduced; } else { prevFrame = curFrame; prevData = curData; } } return(nReduced); }
/// <summary> /// SampleChannel will be called to sample the transformation of a given channel /// at a given time. The given index parameter is for use by the sample function, /// to avoid having to look for the "base" frame each call. It will start out as /// zero in the first call for a given channel. "time" will be monotonically /// increasing for a given channel. /// </summary> /// <param name="achan">The channel to sample from.</param> /// <param name="time">The time to sample at (monotonically increasing).</param> /// <param name="ix">For use by SampleChannel (starts at 0 for each new channel).</param> /// <returns>The sampled keyframe output (allocated by this function).</returns> protected virtual Keyframe SampleChannel(AnimationChannel achan, float time, ref int ix) { Keyframe ret = new Keyframe(); AnimationKeyframe akf0 = achan[ix]; float scale = CalcTransformScale(akf0.Transform); //todo: really should be done in world space, but I'm giving up now float offset = akf0.Transform.Translation.Length(); if (scale > maxScale_) { maxScale_ = scale; } if (offset > maxOffset_) { maxOffset_ = offset; } again: if (ix == achan.Count - 1) { return(KeyframeFromMatrix(akf0.Transform, ret)); } AnimationKeyframe akf1 = achan[ix + 1]; if (akf1.Time.TotalSeconds <= time) { akf0 = akf1; ++ix; goto again; } KeyframeFromMatrix(akf0.Transform, tmpA_); KeyframeFromMatrix(akf1.Transform, tmpB_); Keyframe.Interpolate(tmpA_, tmpB_, (float)((time - akf0.Time.TotalSeconds) / (akf1.Time.TotalSeconds - akf0.Time.TotalSeconds)), ret); return(ret); }