Anim: run bezier handle calculation in parallel #119388
|
@ -28,6 +28,7 @@
|
|||
#include "BLI_math_vector_types.hh"
|
||||
#include "BLI_sort_utils.h"
|
||||
#include "BLI_string_utils.hh"
|
||||
#include "BLI_task.hh"
|
||||
|
||||
#include "BLT_translation.hh"
|
||||
|
||||
|
@ -1245,6 +1246,7 @@ static BezTriple *cycle_offset_triple(
|
|||
|
||||
void BKE_fcurve_handles_recalc_ex(FCurve *fcu, eBezTriple_Flag handle_sel_flag)
|
||||
{
|
||||
|
||||
using namespace blender;
|
||||
/* Error checking:
|
||||
* - Need at least two points.
|
||||
* - Need bezier keys.
|
||||
|
@ -1257,60 +1259,55 @@ void BKE_fcurve_handles_recalc_ex(FCurve *fcu, eBezTriple_Flag handle_sel_flag)
|
|||
}
|
||||
|
||||
/* If the first modifier is Cycles, smooth the curve through the cycle. */
|
||||
BezTriple *first = &fcu->bezt[0], *last = &fcu->bezt[fcu->totvert - 1];
|
||||
BezTriple tmp;
|
||||
|
||||
BezTriple *first = &fcu->bezt[0];
|
||||
BezTriple *last = &fcu->bezt[fcu->totvert - 1];
|
||||
const bool cycle = BKE_fcurve_is_cyclic(fcu) && BEZT_IS_AUTOH(first) && BEZT_IS_AUTOH(last);
|
||||
|
||||
/* Get initial pointers. */
|
||||
BezTriple *bezt = fcu->bezt;
|
||||
BezTriple *prev = cycle_offset_triple(cycle, &tmp, &fcu->bezt[fcu->totvert - 2], last, first);
|
||||
BezTriple *next = (bezt + 1);
|
||||
threading::parallel_for(IndexRange(fcu->totvert), 256, [&](const IndexRange range) {
|
||||
BezTriple tmp;
|
||||
Hans Goudey
commented
I'd just write I'd just write `threading::parallel_for(IndexRange(fcu->totvert), `
|
||||
for (const int i : range) {
|
||||
BezTriple *bezt = &fcu->bezt[i];
|
||||
BezTriple *prev = nullptr;
|
||||
BezTriple *next = nullptr;
|
||||
if (i > 0) {
|
||||
prev = (bezt - 1);
|
||||
}
|
||||
else {
|
||||
prev = cycle_offset_triple(cycle, &tmp, &fcu->bezt[fcu->totvert - 2], last, first);
|
||||
}
|
||||
if (i < fcu->totvert - 1) {
|
||||
next = (bezt + 1);
|
||||
}
|
||||
Sybren A. Stüvel
commented
This can be replaced with This can be replaced with `CLAMP_MAX(bezt->vec[0][0], bezt->vec[1][0]);`, and the below case with `CLAMP_MIN()`.
|
||||
else {
|
||||
next = cycle_offset_triple(cycle, &tmp, &fcu->bezt[1], first, last);
|
||||
}
|
||||
|
||||
/* Loop over all beztriples, adjusting handles. */
|
||||
int a = fcu->totvert;
|
||||
while (a--) {
|
||||
/* Clamp timing of handles to be on either side of beztriple. */
|
||||
if (bezt->vec[0][0] > bezt->vec[1][0]) {
|
||||
bezt->vec[0][0] = bezt->vec[1][0];
|
||||
}
|
||||
if (bezt->vec[2][0] < bezt->vec[1][0]) {
|
||||
bezt->vec[2][0] = bezt->vec[1][0];
|
||||
}
|
||||
/* Clamp timing of handles to be on either side of beztriple. */
|
||||
CLAMP_MAX(bezt->vec[0][0], bezt->vec[1][0]);
|
||||
CLAMP_MIN(bezt->vec[2][0], bezt->vec[1][0]);
|
||||
|
||||
/* Calculate auto-handles. */
|
||||
BKE_nurb_handle_calc_ex(bezt, prev, next, handle_sel_flag, true, fcu->auto_smoothing);
|
||||
/* Calculate auto-handles. */
|
||||
BKE_nurb_handle_calc_ex(bezt, prev, next, handle_sel_flag, true, fcu->auto_smoothing);
|
||||
|
||||
/* For automatic ease in and out. */
|
||||
if (BEZT_IS_AUTOH(bezt) && !cycle) {
|
||||
/* Only do this on first or last beztriple. */
|
||||
if (ELEM(a, 0, fcu->totvert - 1)) {
|
||||
/* Set both handles to have same horizontal value as keyframe. */
|
||||
if (fcu->extend == FCURVE_EXTRAPOLATE_CONSTANT) {
|
||||
bezt->vec[0][1] = bezt->vec[2][1] = bezt->vec[1][1];
|
||||
/* Remember that these keyframes are special, they don't need to be adjusted. */
|
||||
bezt->auto_handle_type = HD_AUTOTYPE_LOCKED_FINAL;
|
||||
/* For automatic ease in and out. */
|
||||
if (BEZT_IS_AUTOH(bezt) && !cycle) {
|
||||
/* Only do this on first or last beztriple. */
|
||||
if (ELEM(i, 0, fcu->totvert - 1)) {
|
||||
/* Set both handles to have same horizontal value as keyframe. */
|
||||
if (fcu->extend == FCURVE_EXTRAPOLATE_CONSTANT) {
|
||||
bezt->vec[0][1] = bezt->vec[2][1] = bezt->vec[1][1];
|
||||
/* Remember that these keyframes are special, they don't need to be adjusted. */
|
||||
bezt->auto_handle_type = HD_AUTOTYPE_LOCKED_FINAL;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Avoid total smoothing failure on duplicate keyframes (can happen during grab). */
|
||||
if (prev && prev->vec[1][0] >= bezt->vec[1][0]) {
|
||||
prev->auto_handle_type = bezt->auto_handle_type = HD_AUTOTYPE_LOCKED_FINAL;
|
||||
/* Avoid total smoothing failure on duplicate keyframes (can happen during grab). */
|
||||
if (prev && prev->vec[1][0] >= bezt->vec[1][0]) {
|
||||
prev->auto_handle_type = bezt->auto_handle_type = HD_AUTOTYPE_LOCKED_FINAL;
|
||||
}
|
||||
}
|
||||
|
||||
/* Advance pointers for next iteration. */
|
||||
prev = bezt;
|
||||
|
||||
if (a == 1) {
|
||||
next = cycle_offset_triple(cycle, &tmp, &fcu->bezt[1], first, last);
|
||||
}
|
||||
else if (next != nullptr) {
|
||||
next++;
|
||||
}
|
||||
|
||||
bezt++;
|
||||
}
|
||||
});
|
||||
|
||||
Iliya Katushenock
commented
If this is relatively cheap, you can take look at If this is relatively cheap, you can take look at `TaskSizeHints`.
|
||||
/* If cyclic extrapolation and Auto Clamp has triggered, ensure it is symmetric. */
|
||||
if (cycle && (first->auto_handle_type != HD_AUTOTYPE_NORMAL ||
|
||||
|
|
Loading…
Reference in New Issue
If
fcu->totvert == 2
thenprev
could be the same asbezt
. The old code didn't have that, as it usedprev = bezt
at the end of the loop (unless I'm missing something, which is entirely possible).The same goes for
next
below, that'll also be the same asbezt
whenbezt
is the last key andtotvert == 2
. That was already the case in the old code, though.Also (in the old code) the negative counting in
a
but the positive order of visiting the keys makes my head hurt. I'm glad you're resolving this.