34#define USE_NONUNIFORM_SCALE
45 ik_constraints.
append(con);
48 if (data->tar ==
nullptr) {
51 if (data->tar->type ==
OB_ARMATURE && data->subtarget[0] == 0) {
57 ik_constraints.
append(con);
75 bPoseChannel *curchan, *pchan_root =
nullptr, *chanlist[256], **oldchan;
82 pchan_tip = pchan_tip->
parent;
86 for (curchan = pchan_tip; curchan; curchan = curchan->
parent) {
90 chanlist[segcount] = curchan;
93 if (segcount == data->rootbone || segcount > 255) {
104 for (target =
static_cast<PoseTarget *
>(
tree->targets.first); target; target = target->
next)
106 curchan =
tree->pchan[target->tip];
108 curchan->
flag &= ~POSE_CHAIN;
121 target->
con = constraint;
122 pchan_tip->
flag &= ~POSE_CHAIN;
124 if (
tree ==
nullptr) {
130 tree->iterations = data->iterations;
131 tree->totchannel = segcount;
135 MEM_callocN(segcount *
sizeof(
void *),
"ik tree pchan"));
137 for (
int a = 0; a < segcount; a++) {
138 tree->pchan[a] = chanlist[segcount - a - 1];
141 target->tip = segcount - 1;
147 tree->iterations = std::max<int>(data->iterations,
tree->iterations);
151 const int size = std::min(segcount,
tree->totchannel);
154 while (a < size && t < tree->totchannel) {
156 for (; t <
tree->totchannel &&
tree->pchan[t] != chanlist[segcount - a - 1]; t++) {
159 if (t >=
tree->totchannel) {
162 for (; a < size && t <
tree->totchannel &&
tree->pchan[t] == chanlist[segcount - a - 1];
169 segcount = segcount - a;
170 target->tip =
tree->totchannel + segcount - 1;
174 for (parent = a - 1; parent <
tree->totchannel; parent++) {
175 if (
tree->pchan[parent] == chanlist[segcount - 1]->parent) {
181 if (parent ==
tree->totchannel) {
186 const int newsize =
tree->totchannel + segcount;
187 oldchan =
tree->pchan;
188 int *oldparent =
tree->parent;
191 MEM_callocN(newsize *
sizeof(
void *),
"ik tree pchan"));
193 memcpy(
tree->pchan, oldchan,
sizeof(
void *) *
tree->totchannel);
194 memcpy(
tree->parent, oldparent,
sizeof(
int) *
tree->totchannel);
199 for (a = 0; a < segcount; a++) {
200 tree->pchan[
tree->totchannel + a] = chanlist[segcount - a - 1];
201 tree->parent[
tree->totchannel + a] =
tree->totchannel + a - 1;
203 tree->parent[
tree->totchannel] = parent;
205 tree->totchannel = newsize;
220 if (constraint->enforce != 0.0 && !(constraint->flag &
CONSTRAINT_OFF)) {
230 float iR_parmat[4][4];
245 float vec[3], ikmat[4][4];
256#ifdef USE_NONUNIFORM_SCALE
267#ifdef USE_NONUNIFORM_SCALE
290 float R_parmat[3][3], identity[3][3];
291 float iR_parmat[3][3];
292 float R_bonemat[3][3];
293 float goalrot[3][3], goalpos[3];
294 float rootmat[4][4], imat[4][4];
295 float goal[4][4], goalinv[4][4];
296 float irest_basis[3][3], full_basis[3][3];
297 float end_pose[4][4], world_pose[4][4];
298 float basis[3][3], rest_basis[3][3], start[3], *ikstretch =
nullptr;
299 float resultinf = 0.0f;
300 int a,
flag, hasstretch = 0, resultblend = 0;
302 IK_Segment *seg, *parent, **iktree, *iktarget;
307 if (
tree->totchannel == 0) {
313 for (a = 0; a <
tree->totchannel; a++) {
315 pchan =
tree->pchan[a];
342 parent = iktree[
tree->parent[a]];
360 if (pchan->
parent && (a > 0)) {
365 start[0] = start[1] = start[2] = 0.0f;
416 pchan =
tree->pchan[0];
431 mul_m4_m4m4(imat, ob->object_to_world().ptr(), rootmat);
436 int poleconstrain = 0;
471 resultinf = (target->con->flag &
CONSTRAINT_OFF) ? 0.0f : target->con->enforce;
474 poleangledata =
data;
475 data->
flag &= ~CONSTRAINT_IK_GETANGLE;
480 if (!resultblend && ((target->con->flag &
CONSTRAINT_OFF) || target->con->enforce != 1.0f)) {
481 float q1[4], q2[4], q[4];
482 float fac = (target->con->flag &
CONSTRAINT_OFF) ? 0.0f : target->con->enforce;
483 float mfac = 1.0f - fac;
485 pchan =
tree->pchan[target->tip];
490 mul_m4_series(world_pose, goalinv, ob->object_to_world().ptr(), end_pose);
493 goalpos[0] = fac * goalpos[0] + mfac * world_pose[3][0];
494 goalpos[1] = fac * goalpos[1] + mfac * world_pose[3][1];
495 goalpos[2] = fac * goalpos[2] + mfac * world_pose[3][2];
504 iktarget = iktree[target->tip];
509 solver, iktarget, goalpos, polepos, data->poleangle, (poleangledata == data));
530 tree->basis_change =
static_cast<float(*)[3][3]
>(
531 MEM_mallocN(
sizeof(
float[3][3]) *
tree->totchannel,
"ik basis change"));
533 ikstretch =
static_cast<float *
>(
MEM_mallocN(
sizeof(
float) *
tree->totchannel,
"ik stretch"));
536 for (a = 0; a <
tree->totchannel; a++) {
541 float parentstretch, stretch;
543 pchan =
tree->pchan[a];
544 parentstretch = (
tree->parent[a] >= 0) ? ikstretch[
tree->parent[a]] : 1.0f;
552 ikstretch[a] = (length == 0.0f) ? 1.0f : (trans[1] +
length) / length;
558 stretch = (parentstretch == 0.0f) ? 1.0f : ikstretch[a] / parentstretch;
565 if (resultblend && resultinf != 1.0f) {
588 if (
tree->basis_change) {
607 ob->
pose->
flag &= ~POSE_WAS_REBUILT;
623 bool has_influence =
false;
625 if (!(target->con->flag &
CONSTRAINT_OFF) && target->con->enforce != 0.0f) {
626 has_influence =
true;
632 for (a = 0; a <
tree->totchannel; a++) {
641 if (!has_influence) {
652 for (a = 0; a <
tree->totchannel; a++) {
656 for (a = 0; a <
tree->totchannel; a++) {
680 while (pchan->iktree.first) {
void BKE_pose_where_is_bone(Depsgraph *depsgraph, Scene *scene, Object *ob, bPoseChannel *pchan, float ctime, bool do_extra)
void BKE_constraint_target_matrix_get(struct Depsgraph *depsgraph, struct Scene *scene, struct bConstraint *con, int index, short ownertype, void *ownerdata, float mat[4][4], float ctime)
#define LISTBASE_FOREACH(type, var, list)
void void BLI_freelistN(struct ListBase *listbase) ATTR_NONNULL(1)
void BLI_addtail(struct ListBase *listbase, void *vlink) ATTR_NONNULL(1)
void BLI_remlink(struct ListBase *listbase, void *vlink) ATTR_NONNULL(1)
MINLINE float square_f(float a)
void mul_m3_v3(const float M[3][3], float r[3])
void mul_m4_m4m4(float R[4][4], const float A[4][4], const float B[4][4])
void copy_m3_m3(float m1[3][3], const float m2[3][3])
void unit_m3(float m[3][3])
void copy_m3_m4(float m1[3][3], const float m2[4][4])
bool invert_m3_m3(float inverse[3][3], const float mat[3][3])
void unit_m4(float m[4][4])
void copy_m4_m3(float m1[4][4], const float m2[3][3])
void normalize_m3(float R[3][3]) ATTR_NONNULL()
#define mul_m4_series(...)
void copy_m4_m4(float m1[4][4], const float m2[4][4])
bool invert_m4_m4(float inverse[4][4], const float mat[4][4])
void mat4_to_size(float size[3], const float M[4][4])
void transpose_m3_m3(float R[3][3], const float M[3][3])
void blend_m3_m3m3(float out[3][3], const float dst[3][3], const float src[3][3], float srcweight)
void mul_m3_m3m3(float R[3][3], const float A[3][3], const float B[3][3])
void mat3_to_size(float size[3], const float M[3][3])
void normalize_m4(float R[4][4]) ATTR_NONNULL()
void interp_qt_qtqt(float q[4], const float a[4], const float b[4], float t)
void quat_to_mat3(float m[3][3], const float q[4])
void mat3_to_quat(float q[4], const float mat[3][3])
void mat4_to_quat(float q[4], const float mat[4][4])
MINLINE void sub_v3_v3v3(float r[3], const float a[3], const float b[3])
MINLINE void mul_v3_fl(float r[3], float f)
MINLINE void copy_v3_v3(float r[3], const float a[3])
MINLINE void add_v3_v3v3(float r[3], const float a[3], const float b[3])
MINLINE float normalize_v3_length(float n[3], float unit_length)
MINLINE float len_v3(const float a[3]) ATTR_WARN_UNUSED_RESULT
@ CONSTRAINT_TYPE_KINEMATIC
@ CONSTRAINT_OBTYPE_OBJECT
Object is a sort of wrapper for general info.
IK_Solver * IK_CreateSolver(IK_Segment *root)
float IK_SolverGetPoleAngle(IK_Solver *solver)
#define IK_STRETCH_STIFF_MAX
void IK_SolverSetPoleVectorConstraint(IK_Solver *solver, IK_Segment *tip, float goal[3], float polegoal[3], float poleangle, int getangle)
void IK_SetParent(IK_Segment *seg, IK_Segment *parent)
void IK_FreeSolver(IK_Solver *solver)
#define IK_STRETCH_STIFF_MIN
IK_Segment * IK_CreateSegment(int flag)
void IK_FreeSegment(IK_Segment *seg)
void IK_SolverAddGoalOrientation(IK_Solver *solver, IK_Segment *tip, float goal[][3], float weight)
void IK_SetLimit(IK_Segment *seg, IK_SegmentAxis axis, float lmin, float lmax)
void IK_SolverAddGoal(IK_Solver *solver, IK_Segment *tip, float goal[3], float weight)
int IK_Solve(IK_Solver *solver, float tolerance, int max_iterations)
void IK_SetTransform(IK_Segment *seg, float start[3], float rest_basis[][3], float basis[][3], float length)
void IK_GetBasisChange(IK_Segment *seg, float basis_change[][3])
void IK_SetStiffness(IK_Segment *seg, IK_SegmentAxis axis, float stiffness)
void IK_GetTranslationChange(IK_Segment *seg, float *translation_change)
Read Guarded memory(de)allocation.
btSequentialImpulseConstraintSolverMt int btPersistentManifold int btTypedConstraint ** constraints
SIMD_FORCE_INLINE btScalar length() const
Return the length of the vector.
void append(const T &value)
const Depsgraph * depsgraph
void iksolver_release_tree(Scene *, Object *ob, float)
static void initialize_posetree(Object *, bPoseChannel *pchan_tip)
static void find_ik_constraints(ListBase *constraints, blender::Vector< bConstraint * > &ik_constraints)
static void free_posetree(PoseTree *tree)
static void where_is_ik_bone(bPoseChannel *pchan, float ik_mat[3][3])
void iksolver_execute_tree(Depsgraph *depsgraph, Scene *scene, Object *ob, bPoseChannel *pchan_root, float ctime)
void iksolver_clear_data(bPose *pose)
void iksolver_initialize_tree(Depsgraph *, Scene *, Object *ob, float)
static void make_dmats(bPoseChannel *pchan)
static void execute_posetree(Depsgraph *depsgraph, Scene *scene, Object *ob, PoseTree *tree)
void *(* MEM_mallocN)(size_t len, const char *str)
void MEM_freeN(void *vmemh)
void *(* MEM_callocN)(size_t len, const char *str)
struct bPoseChannel * parent