private static double InterpolateCamera( int keyFrameIndex, double time, IList <SetCameraData.CameraKeys> keyFrames, SetCameraData.CameraKeys prevKey) { const double N = 1.0 / 512.0; var curKeyFrame = keyFrames[keyFrameIndex]; var nextKeyFrame = keyFrames[keyFrameIndex + 1]; if (prevKey != null) { prevKey.TangentEaseOut = curKeyFrame.TangentEaseOut; } var t = time - curKeyFrame.KeyFrame * N; var tx = (nextKeyFrame.KeyFrame - curKeyFrame.KeyFrame) * N; switch (curKeyFrame.Interpolation) { case Kh2.Motion.Interpolation.Nearest: return(curKeyFrame.Value); case Kh2.Motion.Interpolation.Linear: return(curKeyFrame.Value + ((nextKeyFrame.Value - curKeyFrame.Value) * t / tx)); case Kh2.Motion.Interpolation.Hermite: case (Kh2.Motion.Interpolation) 3: case (Kh2.Motion.Interpolation) 4: var itx = 1.0 / tx; // Perform a cubic hermite interpolation var p0 = curKeyFrame.Value; var p1 = nextKeyFrame.Value; var m0 = curKeyFrame.TangentEaseOut; var m1 = nextKeyFrame.TangentEaseIn; var t2 = t * t * itx; var t3 = t * t * t * itx * itx; return(p0 * (2 * t3 * itx - 3 * t2 * itx + 1) + m0 * (t3 - 2 * t2 + t) + p1 * (-2 * t3 * itx + 3 * t2 * itx) + m1 * (t3 - t2)); default: return(0); } }
private static double GetCameraValue( double time, IList <SetCameraData.CameraKeys> keyFrames, SetCameraData.CameraKeys prevKey) { if (keyFrames.Count == 0) { return(0.0); } if (keyFrames.Count == 1) { return(keyFrames[0].Value); } const int First = 0; var Last = keyFrames.Count - 1; var m = time + 1.0 / 60.0; var currentFrameIndex = (int)(m * 512.0); if (currentFrameIndex > keyFrames[First].KeyFrame - 0x10000000) { if (currentFrameIndex < keyFrames[Last].KeyFrame) { // Do a binary search through all the key frames var left = First; var right = Last; if (right <= 1) { return(InterpolateCamera(right - 1, m, keyFrames, prevKey)); } while (true) { var mid = (left + right) / 2; if (currentFrameIndex >= keyFrames[mid].KeyFrame) { if (currentFrameIndex <= keyFrames[mid].KeyFrame) { return(keyFrames[mid].Value); } left = mid; } else { right = mid; } if (right - left <= 1) { return(InterpolateCamera(right - 1, m, keyFrames, prevKey)); } } } double tangent; var keyFrameDistance = keyFrames[Last].KeyFrame - keyFrames[Last - 1].KeyFrame; if (keyFrames[Last].Interpolation != Kh2.Motion.Interpolation.Linear || keyFrameDistance == 0) { tangent = keyFrames[Last].TangentEaseOut; } else { tangent = (keyFrames[Last].Value - keyFrames[Last - 1].Value) / keyFrameDistance; } return(((currentFrameIndex - (keyFrames[Last].KeyFrame + 0x10000000) + 0x10000000) * tangent) + keyFrames[Last].Value); } else { double tangent; var keyFrameDistance = keyFrames[First + 1].KeyFrame - keyFrames[First].KeyFrame; if (keyFrames[First].Interpolation != Kh2.Motion.Interpolation.Linear || keyFrameDistance == 0) { tangent = keyFrames[First].TangentEaseIn; } else { tangent = (keyFrames[First + 1].Value - keyFrames[First].Value) / keyFrameDistance; } return(-(((keyFrames[First].KeyFrame - currentFrameIndex - 0x10000000) * tangent) - keyFrames[First].Value)); } }