1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
|
/*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
* All rights reserved.
*/
#pragma once
/** \file
* \ingroup bke
*/
#include "BLI_listbase.h"
#ifdef __cplusplus
extern "C" {
#endif
struct AnimationEvalContext;
struct bAction;
struct BMEditMesh;
struct Bone;
struct Depsgraph;
struct IDProperty;
struct ListBase;
struct Main;
struct Mesh;
struct Object;
struct PoseTree;
struct Scene;
struct bArmature;
struct bConstraint;
struct bGPDstroke;
struct bPose;
struct bPoseChannel;
typedef struct EditBone {
struct EditBone *next, *prev;
/** User-Defined Properties on this Bone */
struct IDProperty *prop;
/** Editbones have a one-way link (i.e. children refer
* to parents. This is converted to a two-way link for
* normal bones when leaving editmode. */
struct EditBone *parent;
/** (64 == MAXBONENAME) */
char name[64];
/** Roll along axis. We'll ultimately use the axis/angle method
* for determining the transformation matrix of the bone. The axis
* is tail-head while roll provides the angle. Refer to Graphics
* Gems 1 p. 466 (section IX.6) if it's not already in here somewhere*/
float roll;
/** Orientation and length is implicit during editing */
float head[3];
float tail[3];
/** All joints are considered to have zero rotation with respect to
* their parents. Therefore any rotations specified during the
* animation are automatically relative to the bones' rest positions*/
int flag;
int layer;
char inherit_scale_mode;
/* Envelope distance & weight */
float dist, weight;
/** put them in order! transform uses this as scale */
float xwidth, length, zwidth;
float rad_head, rad_tail;
/* Bendy-Bone parameters */
short segments;
float roll1, roll2;
float curve_in_x, curve_in_y;
float curve_out_x, curve_out_y;
float ease1, ease2;
float scale_in_x, scale_in_y;
float scale_out_x, scale_out_y;
/** for envelope scaling */
float oldlength;
/** Type of next/prev bone handles */
char bbone_prev_type;
char bbone_next_type;
/** Next/prev bones to use as handle references when calculating bbones (optional) */
struct EditBone *bbone_prev;
struct EditBone *bbone_next;
/* Used for display */
/** in Armature space, rest pos matrix */
float disp_mat[4][4];
/** in Armature space, rest pos matrix */
float disp_tail_mat[4][4];
/** in Armature space, rest pos matrix (32 == MAX_BBONE_SUBDIV) */
float disp_bbone_mat[32][4][4];
/** connected child temporary during drawing */
struct EditBone *bbone_child;
/* Used to store temporary data */
union {
struct EditBone *ebone;
struct Bone *bone;
void *p;
int i;
} temp;
} EditBone;
typedef struct PoseTarget {
struct PoseTarget *next, *prev;
struct bConstraint *con; /* the constraint of this target */
int tip; /* index of tip pchan in PoseTree */
} PoseTarget;
typedef struct PoseTree {
struct PoseTree *next, *prev;
int type; /* type of IK that this serves (CONSTRAINT_TYPE_KINEMATIC or ..._SPLINEIK) */
int totchannel; /* number of pose channels */
struct ListBase targets; /* list of targets of the tree */
struct bPoseChannel **pchan; /* array of pose channels */
int *parent; /* and their parents */
float (*basis_change)[3][3]; /* basis change result from solver */
int iterations; /* iterations from the constraint */
int stretch; /* disable stretching */
} PoseTree;
/* Core armature functionality. */
struct bArmature *BKE_armature_add(struct Main *bmain, const char *name);
struct bArmature *BKE_armature_from_object(struct Object *ob);
int BKE_armature_bonelist_count(struct ListBase *lb);
void BKE_armature_bonelist_free(struct ListBase *lb, const bool do_id_user);
void BKE_armature_editbonelist_free(struct ListBase *lb, const bool do_id_user);
void BKE_armature_copy_bone_transforms(struct bArmature *armature_dst,
const struct bArmature *armature_src);
void BKE_armature_transform(struct bArmature *arm, const float mat[4][4], const bool do_props);
/* Bounding box. */
struct BoundBox *BKE_armature_boundbox_get(struct Object *ob);
bool BKE_pose_minmax(
struct Object *ob, float r_min[3], float r_max[3], bool use_hidden, bool use_select);
bool bone_autoside_name(char name[64], int strip_number, short axis, float head, float tail);
struct Bone *BKE_armature_find_bone_name(struct bArmature *arm, const char *name);
void BKE_armature_bone_hash_make(struct bArmature *arm);
void BKE_armature_bone_hash_free(struct bArmature *arm);
bool BKE_armature_bone_flag_test_recursive(const struct Bone *bone, int flag);
void BKE_armature_refresh_layer_used(struct Depsgraph *depsgraph, struct bArmature *arm);
float distfactor_to_bone(
const float vec[3], const float b1[3], const float b2[3], float rad1, float rad2, float rdist);
void BKE_armature_where_is(struct bArmature *arm);
void BKE_armature_where_is_bone(struct Bone *bone,
const struct Bone *bone_parent,
const bool use_recursion);
void BKE_pose_clear_pointers(struct bPose *pose);
void BKE_pose_remap_bone_pointers(struct bArmature *armature, struct bPose *pose);
void BKE_pchan_rebuild_bbone_handles(struct bPose *pose, struct bPoseChannel *pchan);
void BKE_pose_rebuild(struct Main *bmain,
struct Object *ob,
struct bArmature *arm,
const bool do_id_user);
void BKE_pose_ensure(struct Main *bmain,
struct Object *ob,
struct bArmature *arm,
const bool do_id_user);
void BKE_pose_where_is(struct Depsgraph *depsgraph, struct Scene *scene, struct Object *ob);
void BKE_pose_where_is_bone(struct Depsgraph *depsgraph,
struct Scene *scene,
struct Object *ob,
struct bPoseChannel *pchan,
float ctime,
bool do_extra);
void BKE_pose_where_is_bone_tail(struct bPoseChannel *pchan);
/* Evaluate the action and apply it to the pose. If any pose bones are selected, only FCurves that
* relate to those bones are evaluated. */
void BKE_pose_apply_action(struct Object *ob,
struct bAction *action,
struct AnimationEvalContext *anim_eval_context);
void vec_roll_to_mat3(const float vec[3], const float roll, float r_mat[3][3]);
void vec_roll_to_mat3_normalized(const float nor[3], const float roll, float r_mat[3][3]);
void mat3_to_vec_roll(const float mat[3][3], float r_vec[3], float *r_roll);
void mat3_vec_to_roll(const float mat[3][3], const float vec[3], float *r_roll);
/* Common Conversions Between Co-ordinate Spaces */
void BKE_armature_mat_world_to_pose(struct Object *ob,
const float inmat[4][4],
float outmat[4][4]);
void BKE_armature_loc_world_to_pose(struct Object *ob, const float inloc[3], float outloc[3]);
void BKE_armature_mat_pose_to_bone(struct bPoseChannel *pchan,
const float inmat[4][4],
float outmat[4][4]);
void BKE_armature_loc_pose_to_bone(struct bPoseChannel *pchan,
const float inloc[3],
float outloc[3]);
void BKE_armature_mat_bone_to_pose(struct bPoseChannel *pchan,
const float inmat[4][4],
float outmat[4][4]);
void BKE_armature_mat_pose_to_delta(float delta_mat[4][4],
float pose_mat[4][4],
float arm_mat[4][4]);
void BKE_armature_mat_pose_to_bone_ex(struct Depsgraph *depsgraph,
struct Object *ob,
struct bPoseChannel *pchan,
const float inmat[4][4],
float outmat[4][4]);
void BKE_pchan_mat3_to_rot(struct bPoseChannel *pchan, const float mat[3][3], bool use_compat);
void BKE_pchan_rot_to_mat3(const struct bPoseChannel *pchan, float r_mat[3][3]);
void BKE_pchan_apply_mat4(struct bPoseChannel *pchan, const float mat[4][4], bool use_compat);
void BKE_pchan_to_mat4(const struct bPoseChannel *pchan, float r_chanmat[4][4]);
void BKE_pchan_calc_mat(struct bPoseChannel *pchan);
/* Simple helper, computes the offset bone matrix. */
void BKE_bone_offset_matrix_get(const struct Bone *bone, float offs_bone[4][4]);
/* Transformation inherited from the parent bone. These matrices apply the effects of
* HINGE/NO_SCALE/NO_LOCAL_LOCATION options over the pchan loc/rot/scale transformations. */
typedef struct BoneParentTransform {
float rotscale_mat[4][4]; /* parent effect on rotation & scale pose channels */
float loc_mat[4][4]; /* parent effect on location pose channel */
float post_scale[3]; /* additional scale to apply with post-multiply */
} BoneParentTransform;
/* Matrix-like algebra operations on the transform */
void BKE_bone_parent_transform_clear(struct BoneParentTransform *bpt);
void BKE_bone_parent_transform_invert(struct BoneParentTransform *bpt);
void BKE_bone_parent_transform_combine(const struct BoneParentTransform *in1,
const struct BoneParentTransform *in2,
struct BoneParentTransform *result);
void BKE_bone_parent_transform_apply(const struct BoneParentTransform *bpt,
const float inmat[4][4],
float outmat[4][4]);
/* Get the current parent transformation for the given pose bone. */
void BKE_bone_parent_transform_calc_from_pchan(const struct bPoseChannel *pchan,
struct BoneParentTransform *r_bpt);
void BKE_bone_parent_transform_calc_from_matrices(int bone_flag,
int inherit_scale_mode,
const float offs_bone[4][4],
const float parent_arm_mat[4][4],
const float parent_pose_mat[4][4],
struct BoneParentTransform *r_bpt);
/* Rotation Mode Conversions - Used for PoseChannels + Objects... */
void BKE_rotMode_change_values(
float quat[4], float eul[3], float axis[3], float *angle, short oldMode, short newMode);
/* B-Bone support */
#define MAX_BBONE_SUBDIV 32
typedef struct Mat4 {
float mat[4][4];
} Mat4;
typedef struct BBoneSplineParameters {
int segments;
float length;
/* Non-uniform scale correction. */
bool do_scale;
float scale[3];
/* Handle control bone data. */
bool use_prev, prev_bbone;
bool use_next, next_bbone;
float prev_h[3], next_h[3];
float prev_mat[4][4], next_mat[4][4];
/* Control values. */
float ease1, ease2;
float roll1, roll2;
float scale_in_x, scale_in_y, scale_out_x, scale_out_y;
float curve_in_x, curve_in_y, curve_out_x, curve_out_y;
} BBoneSplineParameters;
void BKE_pchan_bbone_handles_get(struct bPoseChannel *pchan,
struct bPoseChannel **r_prev,
struct bPoseChannel **r_next);
void BKE_pchan_bbone_spline_params_get(struct bPoseChannel *pchan,
const bool rest,
struct BBoneSplineParameters *r_param);
void BKE_pchan_bbone_spline_setup(struct bPoseChannel *pchan,
const bool rest,
const bool for_deform,
Mat4 *result_array);
void BKE_pchan_bbone_handles_compute(const BBoneSplineParameters *param,
float h1[3],
float *r_roll1,
float h2[3],
float *r_roll2,
bool ease,
bool offsets);
int BKE_pchan_bbone_spline_compute(struct BBoneSplineParameters *param,
const bool for_deform,
Mat4 *result_array);
void BKE_pchan_bbone_segments_cache_compute(struct bPoseChannel *pchan);
void BKE_pchan_bbone_segments_cache_copy(struct bPoseChannel *pchan,
struct bPoseChannel *pchan_from);
void BKE_pchan_bbone_deform_segment_index(const struct bPoseChannel *pchan,
float pos,
int *r_index,
float *r_blend_next);
/* like EBONE_VISIBLE */
#define PBONE_VISIBLE(arm, bone) \
(CHECK_TYPE_INLINE(arm, bArmature *), \
CHECK_TYPE_INLINE(bone, Bone *), \
(((bone)->layer & (arm)->layer) && !((bone)->flag & BONE_HIDDEN_P)))
#define PBONE_SELECTABLE(arm, bone) \
(PBONE_VISIBLE(arm, bone) && !((bone)->flag & BONE_UNSELECTABLE))
#define PBONE_SELECTED(arm, bone) (((bone)->flag & BONE_SELECTED) & PBONE_VISIBLE(arm, bone))
/* context.selected_pose_bones */
#define FOREACH_PCHAN_SELECTED_IN_OBJECT_BEGIN(_ob, _pchan) \
for (bPoseChannel *_pchan = (_ob)->pose->chanbase.first; _pchan; _pchan = _pchan->next) { \
if (PBONE_VISIBLE(((bArmature *)(_ob)->data), (_pchan)->bone) && \
((_pchan)->bone->flag & BONE_SELECTED)) {
#define FOREACH_PCHAN_SELECTED_IN_OBJECT_END \
} \
} \
((void)0)
/* context.visible_pose_bones */
#define FOREACH_PCHAN_VISIBLE_IN_OBJECT_BEGIN(_ob, _pchan) \
for (bPoseChannel *_pchan = (_ob)->pose->chanbase.first; _pchan; _pchan = _pchan->next) { \
if (PBONE_VISIBLE(((bArmature *)(_ob)->data), (_pchan)->bone)) {
#define FOREACH_PCHAN_VISIBLE_IN_OBJECT_END \
} \
} \
((void)0)
/* Evaluation helpers */
struct bKinematicConstraint;
struct bPose;
struct bSplineIKConstraint;
struct bPoseChannel *BKE_armature_ik_solver_find_root(struct bPoseChannel *pchan,
struct bKinematicConstraint *data);
struct bPoseChannel *BKE_armature_splineik_solver_find_root(struct bPoseChannel *pchan,
struct bSplineIKConstraint *data);
void BKE_pose_splineik_init_tree(struct Scene *scene, struct Object *ob, float ctime);
void BKE_splineik_execute_tree(struct Depsgraph *depsgraph,
struct Scene *scene,
struct Object *ob,
struct bPoseChannel *pchan_root,
float ctime);
void BKE_pose_pchan_index_rebuild(struct bPose *pose);
void BKE_pose_eval_init(struct Depsgraph *depsgraph, struct Scene *scene, struct Object *object);
void BKE_pose_eval_init_ik(struct Depsgraph *depsgraph,
struct Scene *scene,
struct Object *object);
void BKE_pose_eval_bone(struct Depsgraph *depsgraph,
struct Scene *scene,
struct Object *object,
int pchan_index);
void BKE_pose_constraints_evaluate(struct Depsgraph *depsgraph,
struct Scene *scene,
struct Object *object,
int pchan_index);
void BKE_pose_bone_done(struct Depsgraph *depsgraph, struct Object *object, int pchan_index);
void BKE_pose_eval_bbone_segments(struct Depsgraph *depsgraph,
struct Object *object,
int pchan_index);
void BKE_pose_iktree_evaluate(struct Depsgraph *depsgraph,
struct Scene *scene,
struct Object *object,
int rootchan_index);
void BKE_pose_splineik_evaluate(struct Depsgraph *depsgraph,
struct Scene *scene,
struct Object *object,
int rootchan_index);
void BKE_pose_eval_done(struct Depsgraph *depsgraph, struct Object *object);
void BKE_pose_eval_cleanup(struct Depsgraph *depsgraph,
struct Scene *scene,
struct Object *object);
void BKE_pose_eval_proxy_init(struct Depsgraph *depsgraph, struct Object *object);
void BKE_pose_eval_proxy_done(struct Depsgraph *depsgraph, struct Object *object);
void BKE_pose_eval_proxy_cleanup(struct Depsgraph *depsgraph, struct Object *object);
void BKE_pose_eval_proxy_copy_bone(struct Depsgraph *depsgraph,
struct Object *object,
int pchan_index);
/* -------------------------------------------------------------------- */
/** \name Deform 3D Coordinates by Armature (armature_deform.c)
* \{ */
/* Note that we could have a 'BKE_armature_deform_coords' that doesn't take object data
* currently there are no callers for this though. */
void BKE_armature_deform_coords_with_gpencil_stroke(const struct Object *ob_arm,
const struct Object *ob_target,
float (*vert_coords)[3],
float (*vert_deform_mats)[3][3],
int vert_coords_len,
int deformflag,
float (*vert_coords_prev)[3],
const char *defgrp_name,
struct bGPDstroke *gps_target);
void BKE_armature_deform_coords_with_mesh(const struct Object *ob_arm,
const struct Object *ob_target,
float (*vert_coords)[3],
float (*vert_deform_mats)[3][3],
int vert_coords_len,
int deformflag,
float (*vert_coords_prev)[3],
const char *defgrp_name,
const struct Mesh *me_target);
void BKE_armature_deform_coords_with_editmesh(const struct Object *ob_arm,
const struct Object *ob_target,
float (*vert_coords)[3],
float (*vert_deform_mats)[3][3],
int vert_coords_len,
int deformflag,
float (*vert_coords_prev)[3],
const char *defgrp_name,
struct BMEditMesh *em_target);
/** \} */
#ifdef __cplusplus
}
#endif
|