Index: source/blender/blenkernel/intern/fcurve.c =================================================================== --- source/blender/blenkernel/intern/fcurve.c (revision 58284) +++ source/blender/blenkernel/intern/fcurve.c (working copy) @@ -1957,6 +1957,7 @@ unsigned int a; int b; float cvalue = 0.0f; + bool exact = false; /* get pointers */ a = fcu->totvert - 1; @@ -2070,57 +2071,59 @@ } } else { - /* evaltime occurs somewhere in the middle of the curve */ - for (a = 0; prevbezt && bezt && (a < fcu->totvert - 1); a++, prevbezt = bezt, bezt++) { - /* use if the key is directly on the frame, rare cases this is needed else we get 0.0 instead. */ - if (fabsf(bezt->vec[1][0] - evaltime) < SMALL_NUMBER) { - cvalue = bezt->vec[1][1]; + /* evaltime occurs somewhere in the middle of the curve + * use binary search to find bezt + */ + + a = binarysearch_bezt_index(bezts, evaltime, fcu->totvert, &exact); + bezt = bezts; + bezt += a; + prevbezt = bezt - 1; + + if (exact) { + cvalue = bezt->vec[1][1]; + } + else { + if ((prevbezt->ipo == BEZT_IPO_CONST) || (fcu->flag & FCURVE_DISCRETE_VALUES)) { + /* constant (evaltime not relevant, so no interpolation needed) */ + cvalue = prevbezt->vec[1][1]; } - /* evaltime occurs within the interval defined by these two keyframes */ - else if ((prevbezt->vec[1][0] <= evaltime) && (bezt->vec[1][0] >= evaltime)) { - /* value depends on interpolation mode */ - if ((prevbezt->ipo == BEZT_IPO_CONST) || (fcu->flag & FCURVE_DISCRETE_VALUES)) { - /* constant (evaltime not relevant, so no interpolation needed) */ - cvalue = prevbezt->vec[1][1]; + else if (prevbezt->ipo == BEZT_IPO_LIN) { + /* linear - interpolate between values of the two keyframes */ + fac = bezt->vec[1][0] - prevbezt->vec[1][0]; + + /* prevent division by zero */ + if (fac) { + fac = (evaltime - prevbezt->vec[1][0]) / fac; + cvalue = prevbezt->vec[1][1] + (fac * (bezt->vec[1][1] - prevbezt->vec[1][1])); } - else if (prevbezt->ipo == BEZT_IPO_LIN) { - /* linear - interpolate between values of the two keyframes */ - fac = bezt->vec[1][0] - prevbezt->vec[1][0]; - - /* prevent division by zero */ - if (fac) { - fac = (evaltime - prevbezt->vec[1][0]) / fac; - cvalue = prevbezt->vec[1][1] + (fac * (bezt->vec[1][1] - prevbezt->vec[1][1])); - } - else { - cvalue = prevbezt->vec[1][1]; - } - } else { - /* bezier interpolation */ - /* (v1, v2) are the first keyframe and its 2nd handle */ - v1[0] = prevbezt->vec[1][0]; - v1[1] = prevbezt->vec[1][1]; - v2[0] = prevbezt->vec[2][0]; - v2[1] = prevbezt->vec[2][1]; - /* (v3, v4) are the last keyframe's 1st handle + the last keyframe */ - v3[0] = bezt->vec[0][0]; - v3[1] = bezt->vec[0][1]; - v4[0] = bezt->vec[1][0]; - v4[1] = bezt->vec[1][1]; - - /* adjust handles so that they don't overlap (forming a loop) */ - correct_bezpart(v1, v2, v3, v4); - - /* try to get a value for this position - if failure, try another set of points */ - b = findzero(evaltime, v1[0], v2[0], v3[0], v4[0], opl); - if (b) { - berekeny(v1[1], v2[1], v3[1], v4[1], opl, 1); - cvalue = opl[0]; - break; - } + cvalue = prevbezt->vec[1][1]; } } + else { + /* bezier interpolation */ + /* (v1, v2) are the first keyframe and its 2nd handle */ + v1[0] = prevbezt->vec[1][0]; + v1[1] = prevbezt->vec[1][1]; + v2[0] = prevbezt->vec[2][0]; + v2[1] = prevbezt->vec[2][1]; + /* (v3, v4) are the last keyframe's 1st handle + the last keyframe */ + v3[0] = bezt->vec[0][0]; + v3[1] = bezt->vec[0][1]; + v4[0] = bezt->vec[1][0]; + v4[1] = bezt->vec[1][1]; + + /* adjust handles so that they don't overlap (forming a loop) */ + correct_bezpart(v1, v2, v3, v4); + + /* try to get a value for this position - if failure, try another set of points */ + b = findzero(evaltime, v1[0], v2[0], v3[0], v4[0], opl); + if (b) { + berekeny(v1[1], v2[1], v3[1], v4[1], opl, 1); + cvalue = opl[0]; + } + } } }