790 lines
30 KiB
C++
790 lines
30 KiB
C++
/* SPDX-FileCopyrightText: 2001-2002 NaN Holding BV. All rights reserved.
|
|
*
|
|
* SPDX-License-Identifier: GPL-2.0-or-later */
|
|
|
|
#pragma once
|
|
|
|
/** \file
|
|
* \ingroup bke
|
|
*/
|
|
|
|
#include <optional>
|
|
|
|
#include "BLI_bounds_types.hh"
|
|
#include "BLI_function_ref.hh"
|
|
#include "BLI_math_matrix_types.hh"
|
|
#include "BLI_math_vector_types.hh"
|
|
#include "BLI_mutex.hh"
|
|
#include "BLI_set.hh"
|
|
|
|
#include "DNA_armature_types.h"
|
|
#include "DNA_listBase.h"
|
|
|
|
#include "BKE_pose.hh"
|
|
|
|
namespace blender {
|
|
|
|
struct bDeformGroup;
|
|
struct BMEditMesh;
|
|
struct Bone;
|
|
struct Depsgraph;
|
|
struct IDProperty;
|
|
struct Main;
|
|
struct Mesh;
|
|
struct Object;
|
|
struct PoseTree;
|
|
struct Scene;
|
|
struct bArmature;
|
|
struct bConstraint;
|
|
struct bPose;
|
|
struct bPoseChannel;
|
|
struct MDeformVert;
|
|
|
|
enum eRotationModes : short;
|
|
|
|
struct EditBone {
|
|
EditBone *next = nullptr, *prev = nullptr;
|
|
/** User-Defined Properties on this Bone */
|
|
IDProperty *prop = nullptr;
|
|
/** System-Defined Properties storage. */
|
|
IDProperty *system_properties = nullptr;
|
|
/**
|
|
* Edit-bones have a one-way link (i.e. children refer to parents).
|
|
* This is converted to a two-way link for normal bones when leaving edit-mode.
|
|
*/
|
|
EditBone *parent = nullptr;
|
|
char name[/*MAXBONENAME*/ 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 = 0.0f;
|
|
|
|
/** 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.
|
|
*/
|
|
eBone_Flag flag = {};
|
|
int layer = 0;
|
|
int drawtype = 0; /* eArmature_Drawtype */
|
|
eBone_InheritScaleMode inherit_scale_mode = BONE_INHERIT_SCALE_FULL;
|
|
|
|
/* Envelope distance & weight */
|
|
float dist = 0, weight = 0;
|
|
/** put them in order! transform uses this as scale */
|
|
float xwidth = 0, length = 0, zwidth = 0;
|
|
float rad_head = 0, rad_tail = 0;
|
|
|
|
/* Bendy-Bone parameters */
|
|
short segments = 0;
|
|
float roll1 = 0, roll2 = 0;
|
|
float curve_in_x = 0, curve_in_z = 0;
|
|
float curve_out_x = 0, curve_out_z = 0;
|
|
float ease1 = 0, ease2 = 0;
|
|
float scale_in[3] = {}, scale_out[3] = {};
|
|
|
|
/** for envelope scaling */
|
|
float oldlength = 0;
|
|
|
|
/** Mapping of vertices to segments. */
|
|
eBone_BBoneMappingMode bbone_mapping_mode = BBONE_MAPPING_STRAIGHT;
|
|
/** Type of next/prev bone handles */
|
|
eBone_BBoneHandleType bbone_prev_type = BBONE_HANDLE_AUTO;
|
|
eBone_BBoneHandleType bbone_next_type = BBONE_HANDLE_AUTO;
|
|
/** B-Bone flags. */
|
|
eBone_BBoneFlag bbone_flag = {};
|
|
eBone_BBoneHandleFlag bbone_prev_flag = {};
|
|
eBone_BBoneHandleFlag bbone_next_flag = {};
|
|
/** Next/prev bones to use as handle references when calculating bbones (optional) */
|
|
EditBone *bbone_prev = nullptr;
|
|
EditBone *bbone_next = nullptr;
|
|
|
|
/* 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. */
|
|
float disp_bbone_mat[/*MAX_BBONE_SUBDIV*/ 32][4][4] = {};
|
|
|
|
/** connected child temporary during drawing */
|
|
EditBone *bbone_child = nullptr;
|
|
|
|
BoneColor color; /* MUST be named the same as in bPoseChannel and Bone structs. */
|
|
ListBaseT<BoneCollectionReference> bone_collections = {};
|
|
|
|
/* Used to store temporary data */
|
|
union {
|
|
EditBone *ebone = nullptr;
|
|
Bone *bone;
|
|
void *p;
|
|
int i;
|
|
} temp;
|
|
};
|
|
|
|
struct PoseTarget {
|
|
PoseTarget *next, *prev;
|
|
|
|
bConstraint *con; /* the constraint of this target */
|
|
int tip; /* index of tip pchan in PoseTree */
|
|
};
|
|
|
|
struct PoseTree {
|
|
PoseTree *next, *prev;
|
|
|
|
int type; /* type of IK that this serves (CONSTRAINT_TYPE_KINEMATIC or ..._SPLINEIK) */
|
|
int totchannel; /* number of pose channels */
|
|
|
|
ListBaseT<PoseTarget> targets; /* list of targets of the tree */
|
|
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 */
|
|
};
|
|
|
|
/* Core armature functionality. */
|
|
|
|
bArmature *BKE_armature_add(Main *bmain, const char *name);
|
|
bArmature *BKE_armature_from_object(Object *ob);
|
|
int BKE_armature_bonelist_count(const ListBaseT<Bone> *lb);
|
|
void BKE_armature_bonelist_free(ListBaseT<Bone> *lb, bool do_id_user);
|
|
void BKE_armature_editbonelist_free(ListBaseT<EditBone> *lb, bool do_id_user);
|
|
|
|
void BKE_armature_copy_bone_transforms(bArmature *armature_dst, const bArmature *armature_src);
|
|
|
|
void BKE_armature_transform(bArmature *arm, const float mat[4][4], bool do_props);
|
|
|
|
/**
|
|
* Return the posed Armature bounding box in object-local coordinate space.
|
|
*/
|
|
std::optional<Bounds<float3>> BKE_armature_min_max(const Object *ob);
|
|
|
|
using ForeachBoneFn = FunctionRef<void(int index, const Bone &bone)>;
|
|
/**
|
|
* Visit each bone in the armature, in depth-first order.
|
|
*/
|
|
void BKE_armature_foreach_bone(const bArmature &armature, ForeachBoneFn callback);
|
|
|
|
/**
|
|
* Calculate the axis-aligned bounds of `pchan` in object-space,
|
|
* taking into account custom transform when set.
|
|
*
|
|
* `r_min` and `r_max` are expanded to fit `pchan` so the caller must initialize them
|
|
* (typically using #INIT_MINMAX).
|
|
*
|
|
* \note The bounds are calculated based on the head & tail of the bone
|
|
* or the custom object's bounds (if the bone uses a custom object).
|
|
* Visual elements such as the envelopes radius & bendy-bone spline segments are *not* included,
|
|
* making this not so useful for viewport culling.
|
|
*
|
|
* \param use_empty_drawtype: When enabled, the draw type of empty custom-objects is taken into
|
|
* account when calculating the bounds.
|
|
*/
|
|
void BKE_pchan_minmax(const Object *ob,
|
|
bke::PChanBoneConst pchanbone,
|
|
bool use_empty_drawtype,
|
|
float3 &r_min,
|
|
float3 &r_max);
|
|
/**
|
|
* Calculate the axis aligned bounds of the pose of `ob` in object-space.
|
|
*
|
|
* This only considers visible bones. When they are either directly (via a flag on the bone) or
|
|
* indirectly (via bone collections) hidden, they are not part of the bounds calculation. When a
|
|
* bone has a custom bone shape, that is included in the bounding box.
|
|
*
|
|
* \note This uses #BKE_pchan_minmax, see its documentation for details on bounds calculation.
|
|
*
|
|
* \param use_select: When true, only consider selected bones. When false, selection state is
|
|
* ignored and all bones are included in the bounds.
|
|
*/
|
|
std::optional<Bounds<float3>> BKE_pose_minmax(const Object *ob, bool use_select);
|
|
|
|
/**
|
|
* Finds the best possible extension to the name on a particular axis.
|
|
* (For renaming, check for unique names afterwards)
|
|
* \param strip_number: removes number extensions (TODO: not used).
|
|
* \param axis: The axis to name on.
|
|
* \param head: The head coordinate of the bone on the specified axis.
|
|
* \param tail: The tail coordinate of the bone on the specified axis.
|
|
*/
|
|
bool bone_autoside_name(char name[64], int strip_number, short axis, float head, float tail);
|
|
|
|
/**
|
|
* Find the bone with the given name.
|
|
*
|
|
* When doing multiple subsequent calls to this function, consider calling
|
|
* #BKE_armature_bone_hash_make first to hash the bone names and speed up
|
|
* queries.
|
|
*/
|
|
Bone *BKE_armature_find_bone_name(bArmature *arm, const char *name);
|
|
|
|
void BKE_armature_bone_hash_make(bArmature *arm);
|
|
void BKE_armature_bone_hash_free(bArmature *arm);
|
|
|
|
bool BKE_armature_bone_flag_test_recursive(const Bone *bone, int flag);
|
|
|
|
/**
|
|
* Bone influence factor from envelope distance.
|
|
*/
|
|
float distfactor_to_bone(const float3 &position,
|
|
const float3 &head,
|
|
const float3 &tail,
|
|
float radius_head,
|
|
float radius_tail,
|
|
float falloff_distance);
|
|
|
|
/**
|
|
* Updates vectors and matrices on rest-position level, only needed
|
|
* after editing armature itself, now only on reading file.
|
|
*/
|
|
void BKE_armature_where_is(bArmature *arm);
|
|
/**
|
|
* Recursive part, calculates rest-position of entire tree of children.
|
|
* \note Used when exiting edit-mode too.
|
|
*/
|
|
void BKE_armature_where_is_bone(Bone *bone, const Bone *bone_parent, bool use_recursion);
|
|
/**
|
|
* Clear pointers of object's pose
|
|
* (needed in remap case, since we cannot always wait for a complete pose rebuild).
|
|
*/
|
|
void BKE_pose_clear_pointers(bPose *pose);
|
|
/**
|
|
* Update the links for the B-Bone handles from Bone data.
|
|
*/
|
|
void BKE_pchan_rebuild_bbone_handles(bPose *pose, bke::PChanBone pchanbone);
|
|
void BKE_pose_channels_clear_with_null_bone(Object *armature_ob, bool do_id_user);
|
|
/**
|
|
* Only after leave edit-mode, duplicating, validating older files, library syncing.
|
|
*
|
|
* \note pose->flag is set for it.
|
|
*
|
|
* \param bmain: May be NULL, only used to tag depsgraph as being dirty.
|
|
*/
|
|
void BKE_pose_rebuild(Main *bmain, Object *ob, bArmature *arm, bool do_id_user);
|
|
/**
|
|
* Ensures object's pose is rebuilt if needed.
|
|
*
|
|
* \param bmain: May be NULL, only used to tag depsgraph as being dirty.
|
|
*/
|
|
void BKE_pose_ensure(Main *bmain, Object *ob, bArmature *arm, bool do_id_user);
|
|
|
|
/**
|
|
* Ensure the object's pose bone indices are up to date.
|
|
*
|
|
* This is only necessary when calling `pchan->bone_get(armature)`, as that cannot verify the
|
|
* up-to-dateness of the pose bone indices.
|
|
*
|
|
* When calling `pchan->bone_get(object)` the check is performed automatically. However, calling
|
|
* that in a hot loop will cost some performance; passing the armature is preferred in that case.
|
|
*
|
|
* This takes a const Object, because it does not modify anything except its pose channels' runtime
|
|
* field `bone_index`. There is no conceptual change to the object, it's just the bone lookup info
|
|
* that's being refreshed. Ideally the field would be marked `mutable`, but currently the
|
|
* bPoseChannel_runtime struct is part of DNA, which doesn't support that keyword.
|
|
*/
|
|
void BKE_pose_ensure_bone_indices(const Object &pose_object);
|
|
|
|
/**
|
|
* \note This is the only function adding poses.
|
|
* \note This only reads anim data from channels, and writes to channels.
|
|
*/
|
|
void BKE_pose_where_is(Depsgraph *depsgraph, Scene *scene, Object *ob);
|
|
/**
|
|
* The main armature solver, does all constraints excluding IK.
|
|
*
|
|
* \param pchan: pose-channel - validated, as having bone and parent pointer.
|
|
* \param do_extra: when zero skips loc/size/rot, constraints and strip modifiers.
|
|
*/
|
|
void BKE_pose_where_is_bone(Depsgraph *depsgraph,
|
|
Scene *scene,
|
|
Object *ob,
|
|
bPoseChannel *pchan,
|
|
float ctime,
|
|
bool do_extra);
|
|
/**
|
|
* Calculate tail of pose-channel.
|
|
*/
|
|
void BKE_pose_where_is_bone_tail(bke::PChanBone pchanbone);
|
|
|
|
void vec_roll_to_mat3(const float vec[3], float roll, float r_mat[3][3]);
|
|
|
|
/**
|
|
* Calculates the rest matrix of a bone based on its vector and a roll around that vector.
|
|
*/
|
|
void vec_roll_to_mat3_normalized(const float nor[3], float roll, float r_mat[3][3]);
|
|
/**
|
|
* Computes vector and roll based on a rotation.
|
|
* "mat" must contain only a rotation, and no scaling.
|
|
*/
|
|
void mat3_to_vec_roll(const float mat[3][3], float r_vec[3], float *r_roll);
|
|
/**
|
|
* Computes roll around the vector that best approximates the matrix.
|
|
* If `vec` is the Y vector from purely rotational `mat`, result should be exact.
|
|
*/
|
|
void mat3_vec_to_roll(const float mat[3][3], const float vec[3], float *r_roll);
|
|
|
|
/* Common Conversions Between Coordinate Spaces */
|
|
|
|
/**
|
|
* Convert World-Space Matrix to Pose-Space Matrix.
|
|
*/
|
|
void BKE_armature_mat_world_to_pose(Object *ob, const float inmat[4][4], float outmat[4][4]);
|
|
/**
|
|
* Convert World-Space Location to Pose-Space Location
|
|
* \note this cannot be used to convert to pose-space location of the supplied
|
|
* pose-channel into its local space (i.e. *visual*-keyframing).
|
|
*/
|
|
void BKE_armature_loc_world_to_pose(Object *ob, const float inloc[3], float outloc[3]);
|
|
/**
|
|
* Convert Pose-Space Matrix to Bone-Space Matrix.
|
|
* \note this cannot be used to convert to pose-space transforms of the supplied
|
|
* pose-channel into its local space (i.e. *visual*-keyframing).
|
|
*/
|
|
void BKE_armature_mat_pose_to_bone(bke::PChanBoneConst pchanbone,
|
|
const float inmat[4][4],
|
|
float outmat[4][4]);
|
|
/**
|
|
* Convert Pose-Space Location to Bone-Space Location
|
|
* \note this cannot be used to convert to pose-space location of the supplied
|
|
* pose-channel into its local space (i.e. *visual*-keyframing).
|
|
*/
|
|
void BKE_armature_loc_pose_to_bone(bke::PChanBoneConst pchanbone,
|
|
const float inloc[3],
|
|
float outloc[3]);
|
|
/**
|
|
* Convert Bone-Space Matrix to Pose-Space Matrix.
|
|
*/
|
|
void BKE_armature_mat_bone_to_pose(bke::PChanBoneConst pchanbone,
|
|
const float inmat[4][4],
|
|
float outmat[4][4]);
|
|
/**
|
|
* Remove rest-position effects from pose-transform for obtaining
|
|
* 'visual' transformation of pose-channel.
|
|
* (used by the Visual-Keyframing stuff).
|
|
*/
|
|
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(Depsgraph *depsgraph,
|
|
Object *ob,
|
|
const bPoseChannel *pchan,
|
|
const float inmat[4][4],
|
|
float outmat[4][4]);
|
|
|
|
/**
|
|
* Same as #BKE_object_mat3_to_rot().
|
|
*
|
|
* \param use_compat: only applies when the `pchan` is in euler rotation mode. It then picks the
|
|
* closest euler values relative to what the `pchan` already has.
|
|
*/
|
|
void BKE_pchan_mat3_to_rot(bPoseChannel *pchan, const float mat[3][3], bool use_compat);
|
|
/**
|
|
* Same as #BKE_object_rot_to_mat3().
|
|
*/
|
|
void BKE_pchan_rot_to_mat3(const bPoseChannel *pchan, float r_mat[3][3]);
|
|
|
|
/**
|
|
* Returns a quaternion representation of the current rotation of the bone.
|
|
* Euler and Axis Angle will be converted to Quaternion and then returned.
|
|
*/
|
|
float4 BKE_pchan_rot_to_quat(const bPoseChannel &pchan);
|
|
|
|
/**
|
|
* Applies the quaternion rotation to the current rotation of the bone.
|
|
* Depending on the `pchan.rotmode` this modifies either Euler, Axis Angle or Quaternion values.
|
|
*/
|
|
void BKE_pchan_quat_to_rot(bPoseChannel &pchan, const float4 &quat);
|
|
|
|
/**
|
|
* Apply a 4x4 matrix to the pose bone,
|
|
* similar to #BKE_object_apply_mat4().
|
|
*/
|
|
void BKE_pchan_apply_mat4(bPoseChannel *pchan, const float mat[4][4], bool use_compat);
|
|
/**
|
|
* Convert the loc/rot/size to \a r_chanmat (typically #bPoseChannel.chan_mat).
|
|
*/
|
|
void BKE_pchan_to_mat4(bke::PChanBoneConst pchanbone, float r_chanmat[4][4]);
|
|
|
|
/**
|
|
* Convert the loc/rot/size to mat4 (`pchan.chan_mat`),
|
|
* used in `constraint.cc` too.
|
|
*/
|
|
void BKE_pchan_calc_mat(bke::PChanBone pchanbone);
|
|
|
|
/**
|
|
* Simple helper, computes the offset bone matrix:
|
|
* `offs_bone = yoffs(b-1) + root(b) + bonemat(b)`.
|
|
*/
|
|
void BKE_bone_offset_matrix_get(const 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. */
|
|
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 */
|
|
};
|
|
|
|
/* Matrix-like algebra operations on the transform */
|
|
void BKE_bone_parent_transform_clear(BoneParentTransform *bpt);
|
|
void BKE_bone_parent_transform_invert(BoneParentTransform *bpt);
|
|
void BKE_bone_parent_transform_combine(const BoneParentTransform *in1,
|
|
const BoneParentTransform *in2,
|
|
BoneParentTransform *result);
|
|
|
|
void BKE_bone_parent_transform_apply(const BoneParentTransform *bpt,
|
|
const float inmat[4][4],
|
|
float outmat[4][4]);
|
|
|
|
/**
|
|
* Get the current parent transformation for the given pose bone.
|
|
*
|
|
* Construct the matrices (rot/scale and loc)
|
|
* to apply the PoseChannels into the armature (object) space.
|
|
* I.e. (roughly) the `pose_mat(b-1) * yoffs(b-1) * d_root(b) * bone_mat(b)` in the
|
|
* `pose_mat(b)= pose_mat(b-1) * yoffs(b-1) * d_root(b) * bone_mat(b) * chan_mat(b)`
|
|
* ...function.
|
|
*
|
|
* This allows to get the transformations of a bone in its object space,
|
|
* *before* constraints (and IK) get applied (used by pose evaluation code).
|
|
* And reverse: to find pchan transformations needed to place a bone at a given loc/rot/scale
|
|
* in object space (used by interactive transform, and snapping code).
|
|
*
|
|
* Note that, with the HINGE/NO_SCALE/NO_LOCAL_LOCATION options, the location matrix
|
|
* will differ from the rotation/scale matrix...
|
|
*
|
|
* \note This cannot be used to convert to pose-space transforms of the supplied
|
|
* pose-channel into its local space (i.e. *visual*-key-framing).
|
|
* (NOTE(@mont29): I don't understand that, so I keep it :p).
|
|
*/
|
|
void BKE_bone_parent_transform_calc_from_pchan(bke::PChanBoneConst pchanbone,
|
|
BoneParentTransform *r_bpt);
|
|
/**
|
|
* Compute the parent transform using data decoupled from specific data structures.
|
|
*
|
|
* \param bone_flag: #Bone.flag containing settings.
|
|
* \param offs_bone: delta from parent to current arm_mat (or just arm_mat if no parent).
|
|
* \param parent_arm_mat: arm_mat of parent, or NULL.
|
|
* \param parent_pose_mat: pose_mat of parent, or NULL.
|
|
* \param r_bpt: OUTPUT parent transform.
|
|
*/
|
|
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],
|
|
BoneParentTransform *r_bpt);
|
|
|
|
/**
|
|
* Rotation Mode Conversions - Used for Pose-Channels + Objects.
|
|
*
|
|
* Called from RNA when rotation mode changes
|
|
* - the result should be that the rotations given in the provided pointers have had conversions
|
|
* applied (as appropriate), such that the rotation of the element hasn't 'visually' changed.
|
|
*/
|
|
void BKE_rotMode_change_values(float quat[4],
|
|
float eul[3],
|
|
float axis[3],
|
|
float *angle,
|
|
eRotationModes oldMode,
|
|
eRotationModes newMode);
|
|
|
|
/* B-Bone support */
|
|
#define MAX_BBONE_SUBDIV 32
|
|
|
|
struct Mat4 {
|
|
float mat[4][4];
|
|
};
|
|
|
|
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[3], scale_out[3];
|
|
float curve_in_x, curve_in_z, curve_out_x, curve_out_z;
|
|
};
|
|
|
|
/** Sets the location of the pose channel, respecting #bPoseChannel::protectflag. */
|
|
void BKE_pchan_protected_location_set(bPoseChannel *pchan, const float location[3]);
|
|
/** Sets the rotation of the pose channel, respecting the #bPoseChannel::protectflag. Depending on
|
|
* the current rotation mode, this either modifies quaternion, euler or axis angle. */
|
|
void BKE_pchan_protected_rotation_set(bPoseChannel *pchan, const float mat[3][3]);
|
|
/** Sets the location of the pose channel, respecting #bPoseChannel::protectflag. */
|
|
void BKE_pchan_protected_scale_set(bPoseChannel *pchan, const float scale[3]);
|
|
/** Sets the quaternion rotation of the pose channel, respecting #bPoseChannel::protectflag. */
|
|
void BKE_pchan_protected_rotation_quaternion_set(bPoseChannel *pchan, const float quat[4]);
|
|
/** Sets the euler rotation of the pose channel, respecting #bPoseChannel::protectflag. */
|
|
void BKE_pchan_protected_rotation_euler_set(bPoseChannel *pchan, const float rotation_euler[3]);
|
|
/** Sets the axis-angle rotation of the pose channel, respecting #bPoseChannel::protectflag. */
|
|
void BKE_pchan_protected_rotation_axisangle_set(bPoseChannel *pchan,
|
|
const float axis[3],
|
|
float angle);
|
|
|
|
/**
|
|
* Get "next" and "prev" bones - these are used for handle calculations.
|
|
*/
|
|
void BKE_pchan_bbone_handles_get(bke::PChanBoneConst pchanbone,
|
|
bPoseChannel **r_prev,
|
|
bPoseChannel **r_next);
|
|
/**
|
|
* Compute B-Bone spline parameters for the given channel.
|
|
*/
|
|
void BKE_pchan_bbone_spline_params_get(bke::PChanBoneConst pchanbone,
|
|
const bArmature &armature,
|
|
bool rest,
|
|
BBoneSplineParameters *param);
|
|
|
|
/**
|
|
* Fills the array with the desired amount of bone->segments elements.
|
|
* This calculation is done within unit bone space.
|
|
*/
|
|
void BKE_pchan_bbone_spline_setup(bke::PChanBone pchanbone,
|
|
const bArmature &armature,
|
|
bool rest,
|
|
bool for_deform,
|
|
Mat4 *result_array);
|
|
|
|
/**
|
|
* Computes the bezier handle vectors and rolls coming from custom handles.
|
|
*/
|
|
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);
|
|
/**
|
|
* Fills the array with the desired amount of `bone->segments` elements.
|
|
* This calculation is done within unit bone space.
|
|
*/
|
|
int BKE_pchan_bbone_spline_compute(BBoneSplineParameters *param,
|
|
bool for_deform,
|
|
Mat4 *result_array);
|
|
|
|
/**
|
|
* Compute and cache the B-Bone shape in the channel runtime struct.
|
|
*/
|
|
void BKE_pchan_bbone_segments_cache_compute(bke::PChanBone pchanbone, const bArmature &armature);
|
|
/**
|
|
* Copy cached B-Bone segments from one channel to another.
|
|
*/
|
|
void BKE_pchan_bbone_segments_cache_copy(bPoseChannel *pchan, bPoseChannel *pchan_from);
|
|
|
|
/**
|
|
* Calculate index and blend factor for the two B-Bone segment nodes
|
|
* affecting the specified point along the bone.
|
|
*
|
|
* \param bone: Pose channel's armature bone.
|
|
* \param head_tail: head-tail position along the bone (auto-clamped between 0 and 1).
|
|
* \param r_index: OUTPUT index of the first segment joint affecting the point.
|
|
* \param r_blend_next: OUTPUT blend factor between the first and the second segment in [0..1]
|
|
*/
|
|
void BKE_pchan_bbone_deform_clamp_segment_index(const Bone &bone,
|
|
float head_tail,
|
|
int *r_index,
|
|
float *r_blend_next);
|
|
|
|
/**
|
|
* Calculate index and blend factor for the two B-Bone segment nodes
|
|
* affecting the specified point in object (pose) space.
|
|
*
|
|
* \param pchanbone: Pose channel.
|
|
* \param co: Pose space coordinates of the point being deformed.
|
|
* \param r_index: OUTPUT index of the first segment joint affecting the point.
|
|
* \param r_blend_next: OUTPUT blend factor between the first and the second segment in [0..1]
|
|
*/
|
|
void BKE_pchan_bbone_deform_segment_index(bke::PChanBoneConst pchanbone,
|
|
const float *co,
|
|
int *r_index,
|
|
float *r_blend_next);
|
|
|
|
/* context.selected_pose_bones */
|
|
#define FOREACH_PCHAN_SELECTED_IN_OBJECT_BEGIN(_ob, _pchan) \
|
|
for (bPoseChannel *_pchan = (bPoseChannel *)(_ob)->pose->chanbase.first; _pchan; \
|
|
_pchan = _pchan->next) \
|
|
{ \
|
|
if (animrig::bone_is_visible(((bArmature *)(_ob)->data), {_pchan, _pchan->bone_get(*_ob)}) && \
|
|
((_pchan)->flag & POSE_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 = (bPoseChannel *)(_ob)->pose->chanbase.first; _pchan; \
|
|
_pchan = _pchan->next) \
|
|
{ \
|
|
if (animrig::bone_is_visible(((bArmature *)(_ob)->data), {_pchan, pchan->bone_get(*_ob)})) {
|
|
#define FOREACH_PCHAN_VISIBLE_IN_OBJECT_END \
|
|
} \
|
|
} \
|
|
((void)0)
|
|
|
|
/* Evaluation helpers */
|
|
struct bKinematicConstraint;
|
|
struct bPose;
|
|
struct bSplineIKConstraint;
|
|
|
|
bPoseChannel *BKE_armature_ik_solver_find_root(bPoseChannel *pchan, bKinematicConstraint *data);
|
|
bPoseChannel *BKE_armature_splineik_solver_find_root(bPoseChannel *pchan,
|
|
bSplineIKConstraint *data);
|
|
|
|
void BKE_pose_splineik_init_tree(Scene *scene, Object *ob, float ctime);
|
|
void BKE_splineik_execute_tree(
|
|
Depsgraph *depsgraph, Scene *scene, Object *ob, bPoseChannel *pchan_root, float ctime);
|
|
|
|
void BKE_pose_pchan_index_rebuild(bPose *pose);
|
|
|
|
void BKE_pose_eval_init(Depsgraph *depsgraph, Scene *scene, Object *object);
|
|
|
|
void BKE_pose_eval_init_ik(Depsgraph *depsgraph, Scene *scene, Object *object);
|
|
|
|
void BKE_pose_eval_bone(Depsgraph *depsgraph, Scene *scene, Object *object, int pchan_index);
|
|
|
|
void BKE_pose_constraints_evaluate(Depsgraph *depsgraph,
|
|
Scene *scene,
|
|
Object *object,
|
|
int pchan_index);
|
|
|
|
void BKE_pose_bone_done(Depsgraph *depsgraph, Object *object, int pchan_index);
|
|
|
|
void BKE_pose_eval_bbone_segments(Depsgraph *depsgraph, Object *object, int pchan_index);
|
|
|
|
void BKE_pose_iktree_evaluate(Depsgraph *depsgraph,
|
|
Scene *scene,
|
|
Object *object,
|
|
int rootchan_index);
|
|
|
|
void BKE_pose_splineik_evaluate(Depsgraph *depsgraph,
|
|
Scene *scene,
|
|
Object *object,
|
|
int rootchan_index);
|
|
|
|
void BKE_pose_eval_done(Depsgraph *depsgraph, Object *object);
|
|
|
|
void BKE_pose_eval_cleanup(Depsgraph *depsgraph, Scene *scene, Object *object);
|
|
|
|
/* -------------------------------------------------------------------- */
|
|
/** \name Deform 3D Coordinates by Armature (`armature_deform.cc`)
|
|
* \{ */
|
|
|
|
/* 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_curves(const Object &ob_arm,
|
|
const Object &ob_target,
|
|
const ListBaseT<bDeformGroup> *defbase,
|
|
MutableSpan<float3> vert_coords,
|
|
std::optional<Span<float3>> vert_coords_prev,
|
|
std::optional<MutableSpan<float3x3>> vert_deform_mats,
|
|
Span<MDeformVert> dverts,
|
|
int deformflag,
|
|
StringRefNull defgrp_name);
|
|
|
|
void BKE_armature_deform_coords_with_mesh(const Object &ob_arm,
|
|
const Object &ob_target,
|
|
MutableSpan<float3> vert_coords,
|
|
std::optional<Span<float3>> vert_coords_prev,
|
|
std::optional<MutableSpan<float3x3>> vert_deform_mats,
|
|
int deformflag,
|
|
StringRefNull defgrp_name,
|
|
const Mesh *me_target);
|
|
|
|
void BKE_armature_deform_coords_with_editmesh(
|
|
const Object &ob_arm,
|
|
const Object &ob_target,
|
|
MutableSpan<float3> vert_coords,
|
|
std::optional<Span<float3>> vert_coords_prev,
|
|
std::optional<MutableSpan<float3x3>> vert_deform_mats,
|
|
int deformflag,
|
|
StringRefNull defgrp_name,
|
|
const BMEditMesh &em_target);
|
|
|
|
/** \} */
|
|
|
|
namespace bke {
|
|
|
|
struct bArmature_Runtime {
|
|
/**
|
|
* Index of the active collection, -1 if there is no collection active.
|
|
*
|
|
* For UIList support in the user interface. Assigning here does nothing, use
|
|
* `ANIM_armature_bonecoll_active_set` to set the active bone collection.
|
|
*/
|
|
int active_collection_index = 0;
|
|
BoneCollection *active_collection = nullptr;
|
|
|
|
/**
|
|
* Indexable storage for bones. The bone hierarchy is stored depth-first, so a bone is followed
|
|
* by its children.
|
|
*
|
|
* Used by bPoseChan::bone_get() to obtain a bone pointer by index.
|
|
*/
|
|
Array<Bone *> bones;
|
|
uint64_t bones_generation_count = 0;
|
|
/**
|
|
* Mutex to protect the `bones` and `bones_generation_count` fields.
|
|
*
|
|
* This is used when regenerating the bones array, to ensure only a single thread does this. Read
|
|
* access to the bones array is not protected. So far this has worked well; it's not guaranteed
|
|
* that there won't be a race condition, though. */
|
|
Mutex bones_mutex;
|
|
|
|
/** Clear the `bones` array, ensuring it is rebuilt on its next use. */
|
|
void bones_tag_rebuild();
|
|
|
|
/**
|
|
* Return whether the `bones` array has bones (true), or whether it needs rebuilding (false).
|
|
*
|
|
* Note that this returns 'invalid' when the Armature has no bones. This is because the bones
|
|
* array is only used to obtain a bone pointer by index, which means it's only valid to be used
|
|
* when there actually are bones.
|
|
*/
|
|
bool is_bones_array_valid() const;
|
|
};
|
|
|
|
struct SelectedBonesResult {
|
|
bool all_bones_selected = true;
|
|
bool no_bones_selected = true;
|
|
};
|
|
|
|
using SelectedBoneCallback = FunctionRef<void(Bone *bone)>;
|
|
SelectedBonesResult BKE_armature_find_selected_bones(const bArmature *armature,
|
|
SelectedBoneCallback callback);
|
|
|
|
using BoneNameSet = Set<std::string>;
|
|
/**
|
|
* Return a set of names of the selected bones.
|
|
*/
|
|
BoneNameSet BKE_armature_find_selected_bone_names(const bArmature *armature);
|
|
|
|
BoneNameSet BKE_pose_channel_find_selected_names(const Object *object);
|
|
}; // namespace bke
|
|
|
|
} // namespace blender
|