Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorWayde Moss <GuiltyGhost>2021-02-17 07:58:29 +0300
committerWayde Moss <wbmoss_dev@yahoo.com>2021-02-17 08:21:07 +0300
commitc48360c2559acbe1cb8014ca0e81152f2febf199 (patch)
treedea8ef01dfe70cc0d6ea330bd0e15d44bd1e130d /source/blender/blenkernel/intern/anim_sys.c
parent585db47d992700698cedc3e8eee03df92d067833 (diff)
Fix: NLA Blends Non-Animated Upper Channel Values
Issue introduced by my commit: rB40b7929cc040 **User-level Problem**: The issue resulted in a full-replace upper strip with only a Z location channel full-replacing the XY location channels of the lower stack. replaced to default. The expected behavior is that only the Z location channel is affected. **Technical-level Problem**: Before the problematic commit, fcurves were blended as they were read. So only existing animated channels would blend. My recent commit changed the process to read all fcurve values into an isolated upper_snapshot then blend with the lower stack. There is no data stored to know whether the upper snapshot channel values were sampled from fcurves or were default values. Only those sampled from fcurves should be blended. **Solution**: Added a `blend_domain` bitmask member to NlaEvalChannelSnapshot. The blending function only blends values within the `blend_domain`. Sampled fcurve values are now marked as within the `blend_domain`. We also now always copy the lower snapshot to the result snapshot which only matters when they aren't the same. Currently, it's always the same so the change is more for future unseen cases. Reviewed By: sybren, #animation_rigging Differential Revision: https://developer.blender.org/D10339
Diffstat (limited to 'source/blender/blenkernel/intern/anim_sys.c')
-rw-r--r--source/blender/blenkernel/intern/anim_sys.c50
1 files changed, 47 insertions, 3 deletions
diff --git a/source/blender/blenkernel/intern/anim_sys.c b/source/blender/blenkernel/intern/anim_sys.c
index 965dc4e0bec..1d4893f5700 100644
--- a/source/blender/blenkernel/intern/anim_sys.c
+++ b/source/blender/blenkernel/intern/anim_sys.c
@@ -1050,6 +1050,7 @@ static NlaEvalChannelSnapshot *nlaevalchan_snapshot_new(NlaEvalChannel *nec)
nec_snapshot->channel = nec;
nec_snapshot->length = length;
+ nlavalidmask_init(&nec_snapshot->blend_domain, length);
return nec_snapshot;
}
@@ -1059,6 +1060,7 @@ static void nlaevalchan_snapshot_free(NlaEvalChannelSnapshot *nec_snapshot)
{
BLI_assert(!nec_snapshot->is_base);
+ nlavalidmask_free(&nec_snapshot->blend_domain);
MEM_freeN(nec_snapshot);
}
@@ -1751,14 +1753,22 @@ static void nlasnapshot_from_action(PointerRNA *ptr,
continue;
}
- NlaEvalChannelSnapshot *necs = nlaeval_snapshot_ensure_channel(r_snapshot, nec);
if (!nlaevalchan_validate_index_ex(nec, fcu->array_index)) {
continue;
}
+ NlaEvalChannelSnapshot *necs = nlaeval_snapshot_ensure_channel(r_snapshot, nec);
+
float value = evaluate_fcurve(fcu, modified_evaltime);
evaluate_value_fmodifiers(&storage, modifiers, fcu, &value, evaltime);
necs->values[fcu->array_index] = value;
+
+ if (nec->mix_mode == NEC_MIX_QUATERNION) {
+ BLI_bitmap_set_all(necs->blend_domain.ptr, true, 4);
+ }
+ else {
+ BLI_BITMAP_ENABLE(necs->blend_domain.ptr, fcu->array_index);
+ }
}
}
@@ -1863,6 +1873,8 @@ static void nlastrip_evaluate_transition(PointerRNA *ptr,
/** Replace \a snapshot2 NULL channels with base or default values so all channels blend. */
nlasnapshot_ensure_channels(channels, &snapshot2);
+ /** Mark all \a snapshot2 channel's values to blend. */
+ nlasnapshot_enable_all_blend_domain(&snapshot2);
nlasnapshot_blend(
channels, &snapshot1, &snapshot2, NLASTRIP_MODE_REPLACE, nes->strip_time, snapshot);
@@ -2471,6 +2483,18 @@ static void animsys_calculate_nla(PointerRNA *ptr,
/* ---------------------- */
+void nlasnapshot_enable_all_blend_domain(NlaEvalSnapshot *snapshot)
+{
+ for (int i = 0; i < snapshot->size; i++) {
+ NlaEvalChannelSnapshot *necs = nlaeval_snapshot_get(snapshot, i);
+ if (necs == NULL) {
+ continue;
+ }
+
+ BLI_bitmap_set_all(necs->blend_domain.ptr, true, 4);
+ }
+}
+
void nlasnapshot_ensure_channels(NlaEvalData *eval_data, NlaEvalSnapshot *snapshot)
{
LISTBASE_FOREACH (NlaEvalChannel *, nec, &eval_data->channels) {
@@ -2479,7 +2503,12 @@ void nlasnapshot_ensure_channels(NlaEvalData *eval_data, NlaEvalSnapshot *snapsh
}
/** Blends the \a lower_snapshot with the \a upper_snapshot into \a r_blended_snapshot according
- * to the given \a upper_blendmode and \a upper_influence. */
+ * to the given \a upper_blendmode and \a upper_influence.
+ *
+ * For \a upper_snapshot, blending limited to values in the \a blend_domain. For Replace blendmode,
+ * this allows the upper snapshot to have a location XYZ channel where only a subset of values are
+ * blended.
+ */
void nlasnapshot_blend(NlaEvalData *eval_data,
NlaEvalSnapshot *lower_snapshot,
NlaEvalSnapshot *upper_snapshot,
@@ -2507,19 +2536,30 @@ void nlasnapshot_blend(NlaEvalData *eval_data,
NlaEvalChannelSnapshot *result_necs = nlaeval_snapshot_ensure_channel(r_blended_snapshot, nec);
+ /** Always copy \a lower_snapshot to result, irrelevant of whether \a upper_snapshot has a
+ * corresponding channel. This only matters when \a lower_snapshot not the same as
+ * \a r_blended_snapshot. */
+ memcpy(result_necs->values, lower_necs->values, length * sizeof(float));
if (upper_necs == NULL || zero_upper_influence) {
- memcpy(result_necs->values, lower_necs->values, length * sizeof(float));
continue;
}
if (upper_blendmode == NLASTRIP_MODE_COMBINE) {
const int mix_mode = nec->mix_mode;
if (mix_mode == NEC_MIX_QUATERNION) {
+ if (!BLI_BITMAP_TEST_BOOL(upper_necs->blend_domain.ptr, 0)) {
+ continue;
+ }
+
nla_combine_quaternion(
lower_necs->values, upper_necs->values, upper_influence, result_necs->values);
}
else {
for (int j = 0; j < length; j++) {
+ if (!BLI_BITMAP_TEST_BOOL(upper_necs->blend_domain.ptr, j)) {
+ continue;
+ }
+
result_necs->values[j] = nla_combine_value(mix_mode,
nec->base_snapshot.values[j],
lower_necs->values[j],
@@ -2530,6 +2570,10 @@ void nlasnapshot_blend(NlaEvalData *eval_data,
}
else {
for (int j = 0; j < length; j++) {
+ if (!BLI_BITMAP_TEST_BOOL(upper_necs->blend_domain.ptr, j)) {
+ continue;
+ }
+
result_necs->values[j] = nla_blend_value(
upper_blendmode, lower_necs->values[j], upper_necs->values[j], upper_influence);
}