private void FindNextCurve(IReadOnlyList <StreamedFrame> streamFrames, int index, int currentFrameIndex, out int frameIndex, out int curveIndex) { for (frameIndex = currentFrameIndex + 1; frameIndex < streamFrames.Count; frameIndex++) { StreamedFrame frame = streamFrames[frameIndex]; for (curveIndex = 0; curveIndex < frame.Curves.Count; curveIndex++) { StreamedCurveKey curve = frame.Curves[curveIndex]; if (curve.Index == index) { return; } } } // if there is no next curve, use current one frameIndex = currentFrameIndex; StreamedFrame currentFrame = streamFrames[currentFrameIndex]; for (curveIndex = 0; curveIndex < currentFrame.Curves.Count; curveIndex++) { StreamedCurveKey curve = currentFrame.Curves[curveIndex]; if (curve.Index == index) { return; } } throw new Exception($"There is no curve with index {index} in any of current or next frames"); }
public static StreamedCurveKey CalculateStreamedFrame(AnimationCurveTpl <Float> curve, int lhsIndex, int rhsIndex, float timeOffset) { IReadOnlyList <KeyframeTpl <Float> > keyframes = curve.Curve; KeyframeTpl <Float> lhs = keyframes[lhsIndex]; int curveKeyIndex = lhsIndex; KeyframeTpl <Float> rhs = keyframes[rhsIndex]; float frameTime = lhs.Time + timeOffset; //TimeEnd = rhs.Time + timeOffset; float deltaTime = rhs.Time - lhs.Time; if (deltaTime < 0.00009999999747378752) { deltaTime = 0.000099999997f; } float deltaValue = rhs.Value.Value - lhs.Value.Value; float inverseTime = 1.0f / (deltaTime * deltaTime); float outTangent = lhs.OutSlope.Value * deltaTime; float inTangent = rhs.InSlope.Value * deltaTime; float curveKeyCoefX = (inTangent + outTangent - deltaValue - deltaValue) * inverseTime / deltaTime; float curveKeyCoefY = inverseTime * (deltaValue + deltaValue + deltaValue - outTangent - outTangent - inTangent); float curveKeyCoefZ = lhs.OutSlope.Value; float curveKeyValue = lhs.Value.Value; if (lhs.OutSlope.Value == float.PositiveInfinity || rhs.InSlope.Value == float.PositiveInfinity) { curveKeyCoefX = 0.0f; curveKeyCoefY = 0.0f; curveKeyCoefZ = 0.0f; curveKeyValue = lhs.Value.Value; } Vector3f curveKeyCoef = new Vector3f(curveKeyCoefX, curveKeyCoefY, curveKeyCoefZ); StreamedCurveKey curveKey = new StreamedCurveKey(curveKeyIndex, curveKeyValue, curveKeyCoef); return(curveKey); }
private void ProcessStreams(IReadOnlyList <StreamedFrame> streamFrames, AnimationClipBindingConstant bindings, IReadOnlyDictionary <uint, string> tos, float sampleRate) { float[] curveValues = new float[4]; float[] inSlopeValues = new float[4]; float[] outSlopeValues = new float[4]; float interval = 1.0f / sampleRate; // first (index [0]) stream frame is for slope calculation for the first real frame (index [1]) // last one (index [count - 1]) is +Infinity // it is made for slope processing, but we don't need them for (int frameIndex = 1; frameIndex < streamFrames.Count - 1; frameIndex++) { StreamedFrame frame = streamFrames[frameIndex]; for (int curveIndex = 0; curveIndex < frame.Curves.Count;) { StreamedCurveKey curve = frame.Curves[curveIndex]; GenericBinding binding = bindings.FindBinding(curve.Index); GetPreviousFrame(streamFrames, curve.Index, frameIndex, out int prevFrameIndex, out int prevCurveIndex); string path = GetCurvePath(tos, binding.Path); if (binding.IsTransform) { int dimension = binding.TransformType.GetDimension(); for (int key = 0; key < dimension; key++) { StreamedCurveKey keyCurve = frame.Curves[curveIndex]; StreamedFrame prevFrame = streamFrames[prevFrameIndex]; StreamedCurveKey prevKeyCurve = prevFrame.Curves[prevCurveIndex + key]; float deltaTime = frame.Time - prevFrame.Time; curveValues[key] = keyCurve.Value; inSlopeValues[key] = prevKeyCurve.CalculateNextInSlope(deltaTime, keyCurve.Value); outSlopeValues[key] = keyCurve.OutSlope; curveIndex = GetNextCurve(frame, curveIndex); } AddTransformCurve(frame.Time, binding.TransformType, curveValues, inSlopeValues, outSlopeValues, 0, path); } else if (binding.CustomType == BindingCustomType.None) { AddDefaultCurve(binding, path, frame.Time, frame.Curves[curveIndex].Value); curveIndex = GetNextCurve(frame, curveIndex); } else { AddCustomCurve(bindings, binding, path, frame.Time, frame.Curves[curveIndex].Value); curveIndex = GetNextCurve(frame, curveIndex); } } } }
private int GetNextCurve(StreamedFrame frame, int currentCurve) { StreamedCurveKey curve = frame.Curves[currentCurve]; int i = currentCurve + 1; for (; i < frame.Curves.Count; i++) { if (frame.Curves[i].Index != curve.Index) { return(i); } } return(i); }
private void GetPreviousFrame(IReadOnlyList <StreamedFrame> streamFrames, int curveID, int currentFrame, out int frameIndex, out int curveIndex) { for (frameIndex = currentFrame - 1; frameIndex >= 0; frameIndex--) { StreamedFrame frame = streamFrames[frameIndex]; for (curveIndex = 0; curveIndex < frame.Curves.Count; curveIndex++) { StreamedCurveKey curve = frame.Curves[curveIndex]; if (curve.Index == curveID) { return; } } } throw new Exception($"There is no curve with index {curveID} in any of previous frames"); }
private void ProcessStreams(IReadOnlyList <StreamedFrame> streamFrames, AnimationClipBindingConstant bindings, IReadOnlyDictionary <uint, string> tos) { float[] curveValues = new float[4]; float[] inSlopeValues = new float[4]; float[] outSlopeValues = new float[4]; // first (index [0]) stream frame is for slope calculation for the first real frame (index [1]) // last one (index [count - 1]) is +Infinity // it is made for slope processing, but we don't need them for (int frameIndex = 1; frameIndex < streamFrames.Count - 1; frameIndex++) { StreamedFrame frame = streamFrames[frameIndex]; for (int curveIndex = 0; curveIndex < frame.Curves.Count;) { StreamedCurveKey curve = frame.Curves[curveIndex]; if (!GetGenericBinding(bindings, curve.Index, out GenericBinding binding)) { curveIndex++; continue; } //FindPreviousCurve(streamFrames, curve.Index, frameIndex, out int prevFrameIndex, out int prevCurveIndex); //FindNextCurve(streamFrames, curve.Index, frameIndex, out int nextFrameIndex, out int nextCurveIndex); string path = GetCurvePath(tos, binding.Path); int dimension = binding.BindingType.GetDimension(); for (int key = 0; key < dimension; key++) { StreamedCurveKey keyCurve = frame.Curves[curveIndex + key]; //StreamedFrame prevFrame = streamFrames[prevFrameIndex]; //StreamedFrame nextFrame = streamFrames[nextFrameIndex]; //StreamedCurveKey prevKeyCurve = prevFrame.Curves[prevCurveIndex + key]; //StreamedCurveKey nextKeyCurve = nextFrame.Curves[nextCurveIndex + key]; curveValues[key] = keyCurve.Value; #warning TODO: TCB to in/out slope //inSlopeValues[key] = prevKeyCurve.CalculateNextInTangent(keyCurve.Value, nextKeyCurve.Value); //outSlopeValues[key] = keyCurve.CalculateOutTangent(prevKeyCurve.Value, nextKeyCurve.Value); } AddComplexCurve(frame.Time, binding.BindingType, curveValues, inSlopeValues, outSlopeValues, 0, path); curveIndex += dimension; } } }