public BasicFCurve() { KeyFrames = null ; DimCount = 0 ; KeyCount = 0 ; InterpType = BasicFCurveInterpType.Constant ; TargetType = BasicFCurveTargetType.None ; ChannelType = BasicFCurveChannelType.None ; TargetIndex = -1 ; }
void EvalFCurve(BasicFCurve fcurve, float frame, float[] result) { float[] data = fcurve.KeyFrames; int lower = 0; int upper = fcurve.KeyCount - 1; int elementStride = fcurveElementStrides[(int)fcurve.InterpType]; int stride = elementStride * fcurve.DimCount + 1; while (upper - lower > 1) { int center = (upper + lower) / 2; float frame2 = data[stride * center]; if (frame < frame2) { upper = center; } else { lower = center; } } int k1 = stride * lower; int k2 = stride * upper; float f1 = data[k1++]; float f2 = data[k2++]; float t = f2 - f1; if (t != 0.0f) { t = (frame - f1) / t; } BasicFCurveInterpType interp = fcurve.InterpType; if (t <= 0.0f) { interp = BasicFCurveInterpType.Constant; } if (t >= 1.0f) { interp = BasicFCurveInterpType.Constant; k1 = k2; } switch (interp) { case BasicFCurveInterpType.Constant: for (int i = 0; i < fcurve.DimCount; i++) { result[i] = data[k1]; k1 += elementStride; } break; case BasicFCurveInterpType.Linear: for (int i = 0; i < fcurve.DimCount; i++) { float v1 = data[k1++]; float v2 = data[k2++]; result[i] = (v2 - v1) * t + v1; } break; case BasicFCurveInterpType.Hermite: float s = 1.0f - t; float b1 = s * s * t * 3.0f; float b2 = t * t * s * 3.0f; float b0 = s * s * s + b1; float b3 = t * t * t + b2; for (int i = 0; i < fcurve.DimCount; i++) { result[i] = data[k1] * b0 + data[k1 + 2] * b1 + data[k2 + 1] * b2 + data[k2] * b3; k1 += 3; k2 += 3; } break; case BasicFCurveInterpType.Cubic: for (int i = 0; i < fcurve.DimCount; i++) { float fa = f1 + data[k1 + 3]; float fb = f2 + data[k2 + 1]; float u = FindCubicRoot(f1, fa, fb, f2, frame); float v = 1.0f - u; float c1 = v * v * u * 3.0f; float c2 = u * u * v * 3.0f; float c0 = v * v * v + c1; float c3 = u * u * u + c2; result[i] = data[k1] * c0 + data[k1 + 4] * c1 + data[k2 + 2] * c2 + data[k2] * c3; k1 += 5; k2 += 5; } break; case BasicFCurveInterpType.Spherical: var q1 = new Quaternion(data[k1 + 0], data[k1 + 1], data[k1 + 2], data[k1 + 3]); var q2 = new Quaternion(data[k2 + 0], data[k2 + 1], data[k2 + 2], data[k2 + 3]); // [note] ć—§API // var q3 = Quaternion.Slerp( q1, q2, t, 0.0f ) ; var q3 = q1.Slerp(q2, t); result[0] = q3.X; result[1] = q3.Y; result[2] = q3.Z; result[3] = q3.W; break; } }