[Bf-blender-cvs] [27388587e66] temp-nla-strip-alignment: - WIP rough core implementation of strip preblend xform support for animation alignment
Wayde Moss
noreply at git.blender.org
Thu Dec 10 06:13:36 CET 2020
Commit: 27388587e66ab68f44fe34fe688bda6916b165f5
Author: Wayde Moss
Date: Wed Nov 25 01:50:35 2020 -0500
Branches: temp-nla-strip-alignment
https://developer.blender.org/rB27388587e66ab68f44fe34fe688bda6916b165f5
- WIP rough core implementation of strip preblend xform support for animation alignment
===================================================================
M source/blender/blenkernel/intern/anim_sys.c
M source/blender/blenkernel/nla_private.h
===================================================================
diff --git a/source/blender/blenkernel/intern/anim_sys.c b/source/blender/blenkernel/intern/anim_sys.c
index 53c3ef66c84..a1d577259f7 100644
--- a/source/blender/blenkernel/intern/anim_sys.c
+++ b/source/blender/blenkernel/intern/anim_sys.c
@@ -40,7 +40,9 @@
#include "BLT_translation.h"
+#include "DNA_action_types.h"
#include "DNA_anim_types.h"
+#include "DNA_constraint_types.h"
#include "DNA_light_types.h"
#include "DNA_material_types.h"
#include "DNA_object_types.h"
@@ -2931,7 +2933,47 @@ static void nlastrip_evaluate_meta_raw_value(PointerRNA *ptr,
/* unlink this strip's modifiers from the parent's modifiers again */
nlaeval_fmodifiers_split_stacks(&strip->modifiers, modifiers);
}
+/*
+ * lower is also output
+ */
+static void nlaeval_snapshot_blend(NlaEvalData *nlaeval,
+ NlaEvalSnapshot *raw_upper,
+ short upper_blendmode,
+ float upper_influence,
+ NlaEvalSnapshot *lower)
+{
+ nlaeval_snapshot_ensure_size(lower, nlaeval->num_channels);
+
+ for (int i = 0; i < nlaeval->num_channels; i++) {
+ NlaEvalChannelSnapshot *c_upper = nlaeval_snapshot_get(raw_upper, i);
+ if (c_upper == NULL) {
+ continue;
+ }
+
+ NlaEvalChannelSnapshot *c_lower = nlaeval_snapshot_ensure_channel(lower, nec);
+ NlaEvalChannel *nec = c_lower->channel;
+ int mix_mode = c_lower->channel->mix_mode;
+ if (upper_blendmode == NLASTRIP_MODE_COMBINE) {
+ if (mix_mode == NEC_MIX_QUATERNION) {
+ nla_combine_quaternion(c_lower->values, c_upper->values, upper_influence, c_lower->values);
+ }
+ else {
+ float *base_values = nec->base_snapshot.values;
+ for (int j = 0; j < c_lower->length; j++) {
+ c_lower->values[j] = nla_combine_value(
+ mix_mode, base_values[j], c_lower->values[j], c_upper->values[j], upper_influence);
+ }
+ }
+ }
+ else {
+ for (int j = 0; j < c_lower->length; j++) {
+ c_lower->values[j] = nla_blend_value(
+ upper_blendmode, c_lower->values[j], c_upper->values[j], upper_influence);
+ }
+ }
+ }
+}
/* evaluates the given evaluation strip */
void nlastrip_evaluate(PointerRNA *ptr,
NlaEvalData *channels,
@@ -2942,52 +2984,100 @@ void nlastrip_evaluate(PointerRNA *ptr,
const bool flush_to_original,
bool allow_alloc_channels)
{
- NlaStrip *strip = nes->strip;
- /* To prevent potential infinite recursion problems
- * (i.e. transition strip, beside meta strip containing a transition
- * several levels deep inside it),
- * we tag the current strip as being evaluated, and clear this when we leave.
- */
- /* TODO: be careful with this flag, since some edit tools may be running and have
- * set this while animation playback was running. */
- if (strip->flag & NLASTRIP_FLAG_EDIT_TOUCHED) {
- return;
- }
- strip->flag |= NLASTRIP_FLAG_EDIT_TOUCHED;
+ NlaEvalSnapshot snapshot_raw;
+ nlaeval_snapshot_init(&snapshot_raw, channels, NULL);
- /* actions to take depend on the type of strip */
- switch (strip->type) {
- case NLASTRIP_TYPE_CLIP: /* action-clip */
- nlastrip_evaluate_actionclip(ptr, channels, modifiers, nes, snapshot, allow_alloc_channels);
- break;
- case NLASTRIP_TYPE_TRANSITION: /* transition */
- nlastrip_evaluate_transition(ptr,
- channels,
- modifiers,
- nes,
- snapshot,
- anim_eval_context,
- flush_to_original,
- allow_alloc_channels);
- break;
- case NLASTRIP_TYPE_META: /* meta */
- nlastrip_evaluate_meta(ptr,
- channels,
- modifiers,
- nes,
- snapshot,
- anim_eval_context,
- flush_to_original,
- allow_alloc_channels);
- break;
+ short blendmode = 0;
+ float influence = 0;
+ nlastrip_evaluate_raw_value(
+ ptr, channels, NULL, nes, &snapshot_raw, anim_eval_context, &blendmode, &influence);
+
+ /* Apply preblend transforms to each bone's raw snapshot values. */
+ Object *object = (Object *)ptr->owner_id;
+ bPose *pose = object->pose;
+ LISTBASE_FOREACH (NlaStripPreBlendTransform *, preblend, &nes->strip->preblend_transforms) {
+ float world[4][4];
+ loc_eul_size_to_mat4(world, preblend->location, preblend->rotation_euler, preblend->scale);
+
+ LISTBASE_FOREACH (NlaStripPreBlendTransform_BoneName *, bone, &preblend_xform->bones) {
+
+ char name_esc[sizeof(bone->name) * 2];
+ BLI_strescape(name_esc, bone->name, sizeof(name_esc));
+
+ /* Get preblend transform in bone's non-animated local space. */
+ float bone_preblend_matrix[4][4];
+ copy_m4_m4(bone_preblend_matrix, world);
+ bPoseChannel *pose_channel = BKE_pose_channel_find_name(pose, name_esc);
+ BKE_constraint_mat_convertspace(object,
+ pose_channel,
+ bone_preblend_matrix,
+ CONSTRAINT_SPACE_WORLD,
+ CONSTRAINT_SPACE_LOCAL,
+ false);
+
+ char *location_path = BLI_sprintfN("pose.bones[\"\s\"].location", name_esc);
+ NlaEvalChannel *location_channel = nlaevalchan_verify(ptr, channels, location_path);
+ float *location_values =
+ nlaeval_snapshot_ensure_channel(snapshot_raw, location_channel)->values;
+
+ char *rotation_path;
+ switch (pose_channel->rotmode) {
+ case ROT_MODE_QUAT:
+ rotation_path = BLI_sprintfN("pose.bones[\"\s\"].rotation_quaternion", name_esc);
+ break;
+ case ROT_MODE_AXISANGLE:
+ rotation_path = BLI_sprintfN("pose.bones[\"\s\"].rotation_axis_angle", name_esc);
+ break;
+ default:
+ rotation_path = BLI_sprintfN("pose.bones[\"\s\"].rotation_euler", name_esc);
+ break;
+ }
+ NlaEvalChannel *rotation_channel = nlaevalchan_verify(ptr, channels, rotation_path);
+ float *rotation_values =
+ nlaeval_snapshot_ensure_channel(snapshot_raw, rotation_channel)->values;
+
+ char *scale_path = BLI_sprintfN("pose.bones[\"\s\"].scale", name_esc);
+ NlaEvalChannel *scale_channel = nlaevalchan_verify(ptr, channels, scale_path);
+ float *scale_values = nlaeval_snapshot_ensure_channel(snapshot_raw, scale_channel)->values;
+
+ /* Apply preblend transform as a parent transform to bone's action channels.
+ * Results written directly back to raw snapshot. */
+ float raw_snapshot_matrix[4][4];
+ float decomposed_quat[4];
+ switch (pose_channel->rotmode) {
+ case ROT_MODE_QUAT:
+ loc_quat_size_to_mat4(
+ raw_snapshot_matrix, location_values, rotation_values, scale_values);
+ mul_m4_m4m4(raw_snapshot_matrix, bone_preblend_matrix, raw_snapshot_matrix);
+ mat4_decompose(location_values, rotation_values, scale_values, raw_snapshot_matrix);
- default: /* do nothing */
- break;
+ break;
+ case ROT_MODE_AXISANGLE:
+ loc_axisangle_size_to_mat4(
+ raw_snapshot_matrix, location_values, rotation_values, scale_values);
+ mul_m4_m4m4(raw_snapshot_matrix, bone_preblend_matrix, raw_snapshot_matrix);
+ mat4_decompose(location_values, decomposed_quat, scale_values, raw_snapshot_matrix);
+ quat_to_axis_angle(rotation_values, &rotation_values[3], decomposed_quat);
+ break;
+ default:
+ loc_eul_size_to_mat4(
+ raw_snapshot_matrix, location_values, rotation_values, scale_values);
+ mul_m4_m4m4(raw_snapshot_matrix, bone_preblend_matrix, raw_snapshot_matrix);
+ quat_to_eul(rotation_values, decomposed_quat);
+
+ break;
+ }
+
+ MEM_freeN(location_path); // todo: verify correct call
+ MEM_freeN(rotation_path); // todo: verify correct call
+ MEM_freeN(scale_path); // todo: verify correct call
+ }
}
- /* clear temp recursion safe-check */
- strip->flag &= ~NLASTRIP_FLAG_EDIT_TOUCHED;
+ /** Blend raw snapshot with lower snapshot. */
+ nlaeval_snapshot_blend(channels, &snapshot_raw, blendmode, influence, snapshot);
+ nlaeval_snapshot_free_data(&snapshot_raw);
}
/* Removes the effect of the evaluation strip from the snapshot value,
@@ -3037,8 +3127,8 @@ void nlastrip_evaluate_invert_get_lower_values(PointerRNA *ptr,
}
/* Evaluates strip without blending, stored within snapshot. NLAEvalChannelSnapshot
- * raw_value_sampled bits are set for channels sampled. This is only called by transition's invert
- * function. */
+ * raw_value_sampled bits are set for channels sampled. This is only called by transition's
+ * invert function. */
void nlastrip_evaluate_raw_value(PointerRNA *ptr,
NlaEvalData *upper_eval_data,
ListBase *modifiers,
@@ -3070,9 +3160,9 @@ void nlastrip_evaluate_raw_value(PointerRNA *ptr,
break;
case NLASTRIP_TYPE_TRANSITION:
/*
- * If nes is eventually a transition, then nothing is written and no value bitmask is set.
- * This matches the existing behavior that adjacent transitions evaluate to default (lower
- * snapshot or property type default).
+ * If nes is eventually a transition, then nothing is written and no value bitmask is
+ * set. This matches the existing behavior that adjacent transitions evaluate to default
+ * (lower snapshot or property type default).
*
* In normal cases, this case should never happen. This is only called by
* nlastrip_evaluate_transition_invert_get_lower_values() and transitions never reference
@@ -3114,8 +3204,8 @@ void nladata_flush_channels(PointerRNA *ptr,
LISTBASE
@@ Diff output truncated at 10240 characters. @@
More information about the Bf-blender-cvs
mailing list