Blender  V2.93
action_mirror.c
Go to the documentation of this file.
1 /*
2  * This program is free software; you can redistribute it and/or
3  * modify it under the terms of the GNU General Public License
4  * as published by the Free Software Foundation; either version 2
5  * of the License, or (at your option) any later version.
6  *
7  * This program is distributed in the hope that it will be useful,
8  * but WITHOUT ANY WARRANTY; without even the implied warranty of
9  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10  * GNU General Public License for more details.
11  *
12  * You should have received a copy of the GNU General Public License
13  * along with this program; if not, write to the Free Software Foundation,
14  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
15  */
16 
23 #include <math.h>
24 #include <string.h>
25 
26 #include "MEM_guardedalloc.h"
27 
28 #include "DNA_anim_types.h"
29 #include "DNA_armature_types.h"
30 #include "DNA_object_types.h"
31 
32 #include "BLI_blenlib.h"
33 #include "BLI_math.h"
34 #include "BLI_string_utils.h"
35 #include "BLI_utildefines.h"
36 
37 #include "BKE_action.h"
38 #include "BKE_armature.h"
39 #include "BKE_fcurve.h"
40 
41 #include "DEG_depsgraph.h"
42 
43 /* -------------------------------------------------------------------- */
79  float *fcurve_eval;
87 };
88 
93  int index,
94  const char *path,
95  struct FCurvePathCache *fcache)
96 {
97  FCurve *fcu = BKE_fcurve_pathcache_find(fcache, path, index);
98  if (fcu && fcu->bezt) {
99  fkc->fcurve = fcu;
100  }
101 }
102 
107  int fkc_len,
108  const char *path,
109  struct FCurvePathCache *fcache)
110 {
111  FCurve **fcurves = alloca(sizeof(*fcurves) * fkc_len);
112  if (BKE_fcurve_pathcache_find_array(fcache, path, fcurves, fkc_len)) {
113  for (int i = 0; i < fkc_len; i++) {
114  if (fcurves[i] && fcurves[i]->bezt) {
115  fkc[i].fcurve = fcurves[i];
116  }
117  }
118  }
119 }
120 
129  const float *keyed_frames,
130  int keyed_frames_len)
131 {
132  BLI_assert(fkc->fcurve != NULL);
133 
134  /* Cache the F-curve values for `keyed_frames`. */
135  const int fcurve_flag = fkc->fcurve->flag;
136  fkc->fcurve->flag |= FCURVE_MOD_OFF;
137  fkc->fcurve_eval = MEM_mallocN(sizeof(float) * keyed_frames_len, __func__);
138  for (int frame_index = 0; frame_index < keyed_frames_len; frame_index++) {
139  const float evaltime = keyed_frames[frame_index];
140  fkc->fcurve_eval[frame_index] = evaluate_fcurve_only_curve(fkc->fcurve, evaltime);
141  }
142  fkc->fcurve->flag = fcurve_flag;
143 
144  /* Cache the #BezTriple for `keyed_frames`, or leave as NULL. */
145  fkc->bezt_array = MEM_mallocN(sizeof(*fkc->bezt_array) * keyed_frames_len, __func__);
146  BezTriple *bezt = fkc->fcurve->bezt;
147  BezTriple *bezt_end = fkc->fcurve->bezt + fkc->fcurve->totvert;
148 
149  int frame_index = 0;
150  while (frame_index < keyed_frames_len) {
151  const float evaltime = keyed_frames[frame_index];
152  const float bezt_time = roundf(bezt->vec[1][0]);
153  if (bezt_time > evaltime) {
154  fkc->bezt_array[frame_index++] = NULL;
155  }
156  else {
157  if (bezt_time == evaltime) {
158  fkc->bezt_array[frame_index++] = bezt;
159  }
160  bezt++;
161  if (bezt == bezt_end) {
162  break;
163  }
164  }
165  }
166  /* Clear remaining unset keyed_frames (if-any). */
167  while (frame_index < keyed_frames_len) {
168  fkc->bezt_array[frame_index++] = NULL;
169  }
170 }
171 
174 static void action_flip_pchan(Object *ob_arm,
175  const bPoseChannel *pchan,
176  struct FCurvePathCache *fcache)
177 {
178  /* Begin F-Curve pose channel value extraction. */
179  /* Use a fixed buffer size as it's known this can only be at most:
180  * `pose.bones["{MAXBONENAME}"].rotation_quaternion`. */
181  char path_xform[256];
182  char pchan_name_esc[sizeof(((bActionChannel *)NULL)->name) * 2];
183  BLI_str_escape(pchan_name_esc, pchan->name, sizeof(pchan_name_esc));
184  const int path_xform_prefix_len = SNPRINTF(path_xform, "pose.bones[\"%s\"]", pchan_name_esc);
185  char *path_xform_suffix = path_xform + path_xform_prefix_len;
186  const int path_xform_suffix_len = sizeof(path_xform) - path_xform_prefix_len;
187 
188  /* Lookup and assign all available #FCurve channels,
189  * unavailable channels are left NULL. */
190 
203  struct {
204  struct FCurve_KeyCache loc[3], eul[3], quat[4], rotAxis[3], rotAngle, size[3], rotmode;
205  } fkc_pchan = {{{NULL}}};
206 
207 #define FCURVE_ASSIGN_VALUE(id, path_test_suffix, index) \
208  BLI_strncpy(path_xform_suffix, path_test_suffix, path_xform_suffix_len); \
209  action_flip_pchan_cache_fcurve_assign_value(&fkc_pchan.id, index, path_xform, fcache)
210 
211 #define FCURVE_ASSIGN_ARRAY(id, path_test_suffix) \
212  BLI_strncpy(path_xform_suffix, path_test_suffix, path_xform_suffix_len); \
213  action_flip_pchan_cache_fcurve_assign_array( \
214  fkc_pchan.id, ARRAY_SIZE(fkc_pchan.id), path_xform, fcache)
215 
216  FCURVE_ASSIGN_ARRAY(loc, ".location");
217  FCURVE_ASSIGN_ARRAY(eul, ".rotation_euler");
218  FCURVE_ASSIGN_ARRAY(quat, ".rotation_quaternion");
219  FCURVE_ASSIGN_ARRAY(rotAxis, ".rotation_axis_angle");
220  FCURVE_ASSIGN_VALUE(rotAngle, ".rotation_axis_angle", 3);
221  FCURVE_ASSIGN_ARRAY(size, ".scale");
222  FCURVE_ASSIGN_VALUE(rotmode, ".rotation_mode", 0);
223 
224 #undef FCURVE_ASSIGN_VALUE
225 #undef FCURVE_ASSIGN_ARRAY
226 
227  /* Array of F-curves, for convenient access. */
228 #define FCURVE_CHANNEL_LEN (sizeof(fkc_pchan) / sizeof(struct FCurve_KeyCache))
229  FCurve *fcurve_array[FCURVE_CHANNEL_LEN];
230  int fcurve_array_len = 0;
231 
232  for (int chan = 0; chan < FCURVE_CHANNEL_LEN; chan++) {
233  struct FCurve_KeyCache *fkc = (struct FCurve_KeyCache *)(&fkc_pchan) + chan;
234  if (fkc->fcurve != NULL) {
235  fcurve_array[fcurve_array_len++] = fkc->fcurve;
236  }
237  }
238 
239  /* If this pose has no transform channels, there is nothing to do. */
240  if (fcurve_array_len == 0) {
241  return;
242  }
243 
244  /* Calculate an array of frames used by any of the key-frames in `fcurve_array`. */
245  int keyed_frames_len;
246  const float *keyed_frames = BKE_fcurves_calc_keyed_frames(
247  fcurve_array, fcurve_array_len, &keyed_frames_len);
248 
249  /* Initialize the pose channel curve cache from the F-curve. */
250  for (int chan = 0; chan < FCURVE_CHANNEL_LEN; chan++) {
251  struct FCurve_KeyCache *fkc = (struct FCurve_KeyCache *)(&fkc_pchan) + chan;
252  if (fkc->fcurve == NULL) {
253  continue;
254  }
255  action_flip_pchan_cache_init(fkc, keyed_frames, keyed_frames_len);
256  }
257 
258  /* X-axis flipping matrix. */
259  float flip_mtx[4][4];
260  unit_m4(flip_mtx);
261  flip_mtx[0][0] = -1;
262 
263  bPoseChannel *pchan_flip = NULL;
264  char pchan_name_flip[MAXBONENAME];
265  BLI_string_flip_side_name(pchan_name_flip, pchan->name, false, sizeof(pchan_name_flip));
266  if (!STREQ(pchan_name_flip, pchan->name)) {
267  pchan_flip = BKE_pose_channel_find_name(ob_arm->pose, pchan_name_flip);
268  }
269 
270  float arm_mat_inv[4][4];
271  invert_m4_m4(arm_mat_inv, pchan_flip ? pchan_flip->bone->arm_mat : pchan->bone->arm_mat);
272 
273  /* Now flip the transformation & write it back to the F-curves in `fkc_pchan`. */
274 
275  for (int frame_index = 0; frame_index < keyed_frames_len; frame_index++) {
276 
277  /* Temporary pose channel to write values into,
278  * using the `fkc_pchan` values, falling back to the values in the pose channel. */
279  bPoseChannel pchan_temp = *pchan;
280 
281  /* Load the values into the channel. */
282 #define READ_VALUE_FLT(id) \
283  if (fkc_pchan.id.fcurve_eval != NULL) { \
284  pchan_temp.id = fkc_pchan.id.fcurve_eval[frame_index]; \
285  } \
286  ((void)0)
287 
288 #define READ_VALUE_INT(id) \
289  if (fkc_pchan.id.fcurve_eval != NULL) { \
290  pchan_temp.id = floorf(fkc_pchan.id.fcurve_eval[frame_index] + 0.5f); \
291  } \
292  ((void)0)
293 
294 #define READ_ARRAY_FLT(id) \
295  for (int i = 0; i < ARRAY_SIZE(pchan_temp.id); i++) { \
296  READ_VALUE_FLT(id[i]); \
297  } \
298  ((void)0)
299 
300  READ_ARRAY_FLT(loc);
301  READ_ARRAY_FLT(eul);
302  READ_ARRAY_FLT(quat);
303  READ_ARRAY_FLT(rotAxis);
304  READ_VALUE_FLT(rotAngle);
306  READ_VALUE_INT(rotmode);
307 
308 #undef READ_ARRAY_FLT
309 #undef READ_VALUE_FLT
310 #undef READ_VALUE_INT
311 
312  float chan_mat[4][4];
313  BKE_pchan_to_mat4(&pchan_temp, chan_mat);
314 
315  /* Move to the pose-space. */
316  mul_m4_m4m4(chan_mat, pchan->bone->arm_mat, chan_mat);
317 
318  /* Flip the matrix. */
319  mul_m4_m4m4(chan_mat, chan_mat, flip_mtx);
320  mul_m4_m4m4(chan_mat, flip_mtx, chan_mat);
321 
322  /* Move back to bone-space space, using the flipped bone if it exists. */
323  mul_m4_m4m4(chan_mat, arm_mat_inv, chan_mat);
324 
325  BKE_pchan_apply_mat4(&pchan_temp, chan_mat, false);
326 
327  /* Write the values back to the F-curves. */
328 #define WRITE_VALUE_FLT(id) \
329  if (fkc_pchan.id.fcurve_eval != NULL) { \
330  BezTriple *bezt = fkc_pchan.id.bezt_array[frame_index]; \
331  if (bezt != NULL) { \
332  const float delta = pchan_temp.id - bezt->vec[1][1]; \
333  bezt->vec[0][1] += delta; \
334  bezt->vec[1][1] += delta; \
335  bezt->vec[2][1] += delta; \
336  } \
337  } \
338  ((void)0)
339 
340 #define WRITE_ARRAY_FLT(id) \
341  for (int i = 0; i < ARRAY_SIZE(pchan_temp.id); i++) { \
342  WRITE_VALUE_FLT(id[i]); \
343  } \
344  ((void)0)
345 
346  /* Write the values back the the F-curves. */
347  WRITE_ARRAY_FLT(loc);
348  WRITE_ARRAY_FLT(eul);
349  WRITE_ARRAY_FLT(quat);
350  WRITE_ARRAY_FLT(rotAxis);
351  WRITE_VALUE_FLT(rotAngle);
353  /* No need to write back 'rotmode' as it can't be transformed. */
354 
355 #undef WRITE_ARRAY_FLT
356 #undef WRITE_VALUE_FLT
357  }
358 
359  /* Recalculate handles. */
360  for (int i = 0; i < fcurve_array_len; i++) {
361  calchandles_fcurve_ex(fcurve_array[i], 0);
362  }
363 
364  MEM_freeN((void *)keyed_frames);
365 
366  for (int chan = 0; chan < FCURVE_CHANNEL_LEN; chan++) {
367  struct FCurve_KeyCache *fkc = (struct FCurve_KeyCache *)(&fkc_pchan) + chan;
368  if (fkc->fcurve_eval) {
369  MEM_freeN(fkc->fcurve_eval);
370  }
371  if (fkc->bezt_array) {
372  MEM_freeN(fkc->bezt_array);
373  }
374  }
375 }
376 
380 static void action_flip_pchan_rna_paths(struct bAction *act)
381 {
382  const char *path_pose_prefix = "pose.bones[\"";
383  const int path_pose_prefix_len = strlen(path_pose_prefix);
384 
385  /* Tag curves that have renamed f-curves. */
386  LISTBASE_FOREACH (bActionGroup *, agrp, &act->groups) {
387  agrp->flag &= ~AGRP_TEMP;
388  }
389 
390  LISTBASE_FOREACH (FCurve *, fcu, &act->curves) {
391  if (!STRPREFIX(fcu->rna_path, path_pose_prefix)) {
392  continue;
393  }
394 
395  const char *name_esc = fcu->rna_path + path_pose_prefix_len;
396  const char *name_esc_end = BLI_str_escape_find_quote(name_esc);
397 
398  /* While unlikely, an RNA path could be malformed. */
399  if (UNLIKELY(name_esc_end == NULL)) {
400  continue;
401  }
402 
403  char name[MAXBONENAME];
404  const size_t name_esc_len = (size_t)(name_esc_end - name_esc);
405  const size_t name_len = BLI_str_unescape(name, name_esc, name_esc_len);
406 
407  /* While unlikely, data paths could be constructed that have longer names than
408  * are currently supported. */
409  if (UNLIKELY(name_len >= sizeof(name))) {
410  continue;
411  }
412 
413  /* When the flipped name differs, perform the rename. */
414  char name_flip[MAXBONENAME];
415  BLI_string_flip_side_name(name_flip, name, false, sizeof(name_flip));
416  if (!STREQ(name_flip, name)) {
417  char name_flip_esc[MAXBONENAME * 2];
418  BLI_str_escape(name_flip_esc, name_flip, sizeof(name_flip_esc));
419  char *path_flip = BLI_sprintfN("pose.bones[\"%s%s", name_flip_esc, name_esc_end);
420  MEM_freeN(fcu->rna_path);
421  fcu->rna_path = path_flip;
422 
423  if (fcu->grp != NULL) {
424  fcu->grp->flag |= AGRP_TEMP;
425  }
426  }
427  }
428 
429  /* Rename tagged groups. */
430  LISTBASE_FOREACH (bActionGroup *, agrp, &act->groups) {
431  if ((agrp->flag & AGRP_TEMP) == 0) {
432  continue;
433  }
434  agrp->flag &= ~AGRP_TEMP;
435  char name_flip[MAXBONENAME];
436  BLI_string_flip_side_name(name_flip, agrp->name, false, sizeof(name_flip));
437  if (!STREQ(name_flip, agrp->name)) {
438  STRNCPY(agrp->name, name_flip);
439  }
440  }
441 }
442 
443 void BKE_action_flip_with_pose(struct bAction *act, struct Object *ob_arm)
444 {
445  struct FCurvePathCache *fcache = BKE_fcurve_pathcache_create(&act->curves);
446  int i;
447  LISTBASE_FOREACH_INDEX (bPoseChannel *, pchan, &ob_arm->pose->chanbase, i) {
448  action_flip_pchan(ob_arm, pchan, fcache);
449  }
451 
453 
455 }
456 
Blender kernel action and pose functionality.
struct bPoseChannel * BKE_pose_channel_find_name(const struct bPose *pose, const char *name)
void BKE_pchan_to_mat4(const struct bPoseChannel *pchan, float r_chanmat[4][4])
void BKE_pchan_apply_mat4(struct bPoseChannel *pchan, const float mat[4][4], bool use_compat)
Definition: armature.c:1951
struct FCurvePathCache * BKE_fcurve_pathcache_create(ListBase *list)
Definition: fcurve_cache.c:78
float * BKE_fcurves_calc_keyed_frames(struct FCurve **fcurve_array, const int fcurve_array_len, int *r_frames_len)
Definition: fcurve.c:885
float evaluate_fcurve_only_curve(struct FCurve *fcu, float evaltime)
Definition: fcurve.c:2193
void BKE_fcurve_pathcache_destroy(struct FCurvePathCache *fcache)
Definition: fcurve_cache.c:127
void calchandles_fcurve_ex(struct FCurve *fcu, eBezTriple_Flag handle_sel_flag)
Definition: fcurve.c:1302
struct FCurve * BKE_fcurve_pathcache_find(struct FCurvePathCache *fcache, const char rna_path[], const int array_index)
int BKE_fcurve_pathcache_find_array(struct FCurvePathCache *fcache, const char *rna_path, struct FCurve **fcurve_result, int fcurve_result_len)
Definition: fcurve_cache.c:163
#define BLI_assert(a)
Definition: BLI_assert.h:58
#define LISTBASE_FOREACH(type, var, list)
Definition: BLI_listbase.h:172
#define LISTBASE_FOREACH_INDEX(type, var, list, index_var)
Definition: BLI_listbase.h:180
void mul_m4_m4m4(float R[4][4], const float A[4][4], const float B[4][4])
Definition: math_matrix.c:262
void unit_m4(float m[4][4])
Definition: rct.c:1140
bool invert_m4_m4(float R[4][4], const float A[4][4])
Definition: math_matrix.c:1278
size_t size_t char * BLI_sprintfN(const char *__restrict format,...) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1) ATTR_MALLOC ATTR_PRINTF_FORMAT(1
#define STRNCPY(dst, src)
Definition: BLI_string.h:163
#define SNPRINTF(dst, format,...)
Definition: BLI_string.h:165
size_t size_t char size_t BLI_str_escape(char *__restrict dst, const char *__restrict src, const size_t dst_maxncpy) ATTR_NONNULL()
Definition: string.c:333
size_t BLI_str_unescape(char *__restrict dst, const char *__restrict src, const size_t src_maxncpy) ATTR_NONNULL()
Definition: string.c:375
const char * BLI_str_escape_find_quote(const char *str) ATTR_NONNULL()
Definition: string.c:410
void BLI_string_flip_side_name(char *r_name, const char *from_name, const bool strip_number, const size_t name_len)
Definition: string_utils.c:159
#define STRPREFIX(a, b)
#define UNLIKELY(x)
#define STREQ(a, b)
void DEG_id_tag_update(struct ID *id, int flag)
@ ID_RECALC_COPY_ON_WRITE
Definition: DNA_ID.h:654
@ AGRP_TEMP
@ FCURVE_MOD_OFF
#define MAXBONENAME
Object is a sort of wrapper for general info.
Read Guarded memory(de)allocation.
#define READ_VALUE_FLT(id)
#define WRITE_ARRAY_FLT(id)
static void action_flip_pchan_cache_fcurve_assign_value(struct FCurve_KeyCache *fkc, int index, const char *path, struct FCurvePathCache *fcache)
Definition: action_mirror.c:92
void BKE_action_flip_with_pose(struct bAction *act, struct Object *ob_arm)
static void action_flip_pchan_cache_init(struct FCurve_KeyCache *fkc, const float *keyed_frames, int keyed_frames_len)
#define READ_VALUE_INT(id)
#define FCURVE_ASSIGN_ARRAY(id, path_test_suffix)
#define FCURVE_CHANNEL_LEN
static void action_flip_pchan_rna_paths(struct bAction *act)
static void action_flip_pchan_cache_fcurve_assign_array(struct FCurve_KeyCache *fkc, int fkc_len, const char *path, struct FCurvePathCache *fcache)
#define WRITE_VALUE_FLT(id)
#define READ_ARRAY_FLT(id)
static void action_flip_pchan(Object *ob_arm, const bPoseChannel *pchan, struct FCurvePathCache *fcache)
#define FCURVE_ASSIGN_VALUE(id, path_test_suffix, index)
float evaltime
Definition: bpy_driver.c:181
static DBVT_INLINE btScalar size(const btDbvtVolume &a)
Definition: btDbvt.cpp:52
void(* MEM_freeN)(void *vmemh)
Definition: mallocn.c:41
void *(* MEM_mallocN)(size_t len, const char *str)
Definition: mallocn.c:47
float vec[3][3]
float arm_mat[4][4]
float * fcurve_eval
Definition: action_mirror.c:79
BezTriple ** bezt_array
Definition: action_mirror.c:86
BezTriple * bezt
short flag
unsigned int totvert
struct bPose * pose
ListBase curves
ListBase groups
struct Bone * bone
ListBase chanbase