diff options
author | Brecht Van Lommel <brechtvanlommel@pandora.be> | 2007-10-24 18:58:31 +0400 |
---|---|---|
committer | Brecht Van Lommel <brechtvanlommel@pandora.be> | 2007-10-24 18:58:31 +0400 |
commit | 30be716fc8e0ada286a94a53bf64dc5d16402c24 (patch) | |
tree | 6d5bbd71a1eea495afabfe7b93e8556b50dbab58 /source/blender/blenkernel/intern | |
parent | 79224961836db454b454f20479a76b83e3eed3bc (diff) |
Pole Target for IK
==================
This adds an extra target to the IK solver constraint to define the
roll of the IK chain.
http://www.blender.org/development/current-projects/changes-since-244/inverse-kinematics/
Also fixes a crashes using ctrl+I to set an IK constraint on a bone
due to the recent constraints refactor.
Diffstat (limited to 'source/blender/blenkernel/intern')
-rw-r--r-- | source/blender/blenkernel/intern/armature.c | 43 | ||||
-rw-r--r-- | source/blender/blenkernel/intern/constraint.c | 90 |
2 files changed, 86 insertions, 47 deletions
diff --git a/source/blender/blenkernel/intern/armature.c b/source/blender/blenkernel/intern/armature.c index 09a7b2a8dcc..38a6a05017c 100644 --- a/source/blender/blenkernel/intern/armature.c +++ b/source/blender/blenkernel/intern/armature.c @@ -1512,7 +1512,7 @@ static void execute_posetree(Object *ob, PoseTree *tree) IK_Segment *seg, *parent, **iktree, *iktarget; IK_Solver *solver; PoseTarget *target; - bKinematicConstraint *data; + bKinematicConstraint *data, *poleangledata=NULL; Bone *bone; if (tree->totchannel == 0) @@ -1624,12 +1624,15 @@ static void execute_posetree(Object *ob, PoseTree *tree) Mat4Invert (goalinv, imat); for (target=tree->targets.first; target; target=target->next) { + float polepos[3]; + int poleconstrain= 0; + data= (bKinematicConstraint*)target->con->data; /* 1.0=ctime, we pass on object for auto-ik (owner-type here is object, even though * strictly speaking, it is a posechannel) */ - get_constraint_target_matrix(target->con, CONSTRAINT_OBTYPE_OBJECT, ob, rootmat, 1.0); + get_constraint_target_matrix(target->con, 0, CONSTRAINT_OBTYPE_OBJECT, ob, rootmat, 1.0); /* and set and transform goal */ Mat4MulMat4(goal, rootmat, goalinv); @@ -1637,6 +1640,26 @@ static void execute_posetree(Object *ob, PoseTree *tree) VECCOPY(goalpos, goal[3]); Mat3CpyMat4(goalrot, goal); + /* same for pole vector target */ + if(data->poletar) { + get_constraint_target_matrix(target->con, 1, CONSTRAINT_OBTYPE_OBJECT, ob, rootmat, 1.0); + + if(data->flag & CONSTRAINT_IK_SETANGLE) { + /* don't solve IK when we are setting the pole angle */ + break; + } + else { + Mat4MulMat4(goal, rootmat, goalinv); + VECCOPY(polepos, goal[3]); + poleconstrain= 1; + + if(data->flag & CONSTRAINT_IK_GETANGLE) { + poleangledata= data; + data->flag &= ~CONSTRAINT_IK_GETANGLE; + } + } + } + /* do we need blending? */ if (target->con->enforce!=1.0) { float q1[4], q2[4], q[4]; @@ -1664,14 +1687,24 @@ static void execute_posetree(Object *ob, PoseTree *tree) iktarget= iktree[target->tip]; - if(data->weight != 0.0) + if(data->weight != 0.0) { + if(poleconstrain) + IK_SolverSetPoleVectorConstraint(solver, iktarget, goalpos, + polepos, data->poleangle*M_PI/180, (poleangledata == data)); IK_SolverAddGoal(solver, iktarget, goalpos, data->weight); - if((data->flag & CONSTRAINT_IK_ROT) && (data->orientweight != 0.0) && (data->flag & CONSTRAINT_IK_AUTO)==0) - IK_SolverAddGoalOrientation(solver, iktarget, goalrot, data->orientweight); + } + if((data->flag & CONSTRAINT_IK_ROT) && (data->orientweight != 0.0)) + if((data->flag & CONSTRAINT_IK_AUTO)==0) + IK_SolverAddGoalOrientation(solver, iktarget, goalrot, + data->orientweight); } /* solve */ IK_Solve(solver, 0.0f, tree->iterations); + + if(poleangledata) + poleangledata->poleangle= IK_SolverGetPoleAngle(solver)*180/M_PI; + IK_FreeSolver(solver); /* gather basis changes */ diff --git a/source/blender/blenkernel/intern/constraint.c b/source/blender/blenkernel/intern/constraint.c index 9dce9c3a611..a8305a7dec1 100644 --- a/source/blender/blenkernel/intern/constraint.c +++ b/source/blender/blenkernel/intern/constraint.c @@ -804,12 +804,12 @@ static void default_get_tarmat (bConstraint *con, bConstraintOb *cob, bConstrain * (Hopefully all compilers will be happy with the lines with just a space on them. Those are * really just to help this code easier to read) */ -#define SINGLETARGET_GET_TARS(con, data, ct, list) \ +#define SINGLETARGET_GET_TARS(con, datatar, datasubtarget, ct, list) \ { \ ct= MEM_callocN(sizeof(bConstraintTarget), "tempConstraintTarget"); \ \ - ct->tar= data->tar; \ - strcpy(ct->subtarget, data->subtarget); \ + ct->tar= datatar; \ + strcpy(ct->subtarget, datasubtarget); \ ct->space= con->tarspace; \ ct->flag= CONSTRAINT_TAR_TEMP; \ \ @@ -827,11 +827,11 @@ static void default_get_tarmat (bConstraint *con, bConstraintOb *cob, bConstrain * (Hopefully all compilers will be happy with the lines with just a space on them. Those are * really just to help this code easier to read) */ -#define SINGLETARGETNS_GET_TARS(con, data, ct, list) \ +#define SINGLETARGETNS_GET_TARS(con, datatar, ct, list) \ { \ ct= MEM_callocN(sizeof(bConstraintTarget), "tempConstraintTarget"); \ \ - ct->tar= data->tar; \ + ct->tar= datatar; \ ct->space= con->tarspace; \ ct->flag= CONSTRAINT_TAR_TEMP; \ \ @@ -845,16 +845,16 @@ static void default_get_tarmat (bConstraint *con, bConstraintOb *cob, bConstrain * (Hopefully all compilers will be happy with the lines with just a space on them. Those are * really just to help this code easier to read) */ -#define SINGLETARGET_FLUSH_TARS(con, data, ct, list, nocopy) \ +#define SINGLETARGET_FLUSH_TARS(con, datatar, datasubtarget, ct, list, nocopy) \ { \ if (ct) { \ if (nocopy == 0) { \ - data->tar= ct->tar; \ - strcpy(data->subtarget, ct->subtarget); \ + datatar= ct->tar; \ + strcpy(datasubtarget, ct->subtarget); \ con->tarspace= ct->space; \ } \ \ - BLI_freelistN(list); \ + BLI_freelinkN(list, ct); \ } \ } @@ -863,15 +863,15 @@ static void default_get_tarmat (bConstraint *con, bConstraintOb *cob, bConstrain * (Hopefully all compilers will be happy with the lines with just a space on them. Those are * really just to help this code easier to read) */ -#define SINGLETARGETNS_FLUSH_TARS(con, data, ct, list, nocopy) \ +#define SINGLETARGETNS_FLUSH_TARS(con, datatar, ct, list, nocopy) \ { \ if (ct) { \ if (nocopy == 0) { \ - data->tar= ct->tar; \ + datatar= ct->tar; \ con->tarspace= ct->space; \ } \ \ - BLI_freelistN(list); \ + BLI_freelinkN(list, ct); \ } \ } @@ -894,7 +894,7 @@ static void childof_get_tars (bConstraint *con, ListBase *list) bConstraintTarget *ct; /* standard target-getting macro for single-target constraints */ - SINGLETARGET_GET_TARS(con, data, ct, list) + SINGLETARGET_GET_TARS(con, data->tar, data->subtarget, ct, list) } } @@ -905,7 +905,7 @@ static void childof_flush_tars (bConstraint *con, ListBase *list, short nocopy) bConstraintTarget *ct= list->first; /* the following macro is used for all standard single-target constraints */ - SINGLETARGET_FLUSH_TARS(con, data, ct, list, nocopy) + SINGLETARGET_FLUSH_TARS(con, data->tar, data->subtarget, ct, list, nocopy) } } @@ -992,7 +992,7 @@ static void trackto_get_tars (bConstraint *con, ListBase *list) bConstraintTarget *ct; /* standard target-getting macro for single-target constraints */ - SINGLETARGET_GET_TARS(con, data, ct, list) + SINGLETARGET_GET_TARS(con, data->tar, data->subtarget, ct, list) } } @@ -1003,7 +1003,7 @@ static void trackto_flush_tars (bConstraint *con, ListBase *list, short nocopy) bConstraintTarget *ct= list->first; /* the following macro is used for all standard single-target constraints */ - SINGLETARGET_FLUSH_TARS(con, data, ct, list, nocopy) + SINGLETARGET_FLUSH_TARS(con, data->tar, data->subtarget, ct, list, nocopy) } } @@ -1169,7 +1169,8 @@ static void kinematic_get_tars (bConstraint *con, ListBase *list) bConstraintTarget *ct; /* standard target-getting macro for single-target constraints */ - SINGLETARGET_GET_TARS(con, data, ct, list) + SINGLETARGET_GET_TARS(con, data->tar, data->subtarget, ct, list) + SINGLETARGET_GET_TARS(con, data->poletar, data->polesubtarget, ct, list) } } @@ -1180,7 +1181,9 @@ static void kinematic_flush_tars (bConstraint *con, ListBase *list, short nocopy bConstraintTarget *ct= list->first; /* the following macro is used for all standard single-target constraints */ - SINGLETARGET_FLUSH_TARS(con, data, ct, list, nocopy) + SINGLETARGET_FLUSH_TARS(con, data->tar, data->subtarget, ct, list, nocopy) + ct= ct->next; + SINGLETARGET_FLUSH_TARS(con, data->poletar, data->polesubtarget, ct, list, nocopy) } } @@ -1245,7 +1248,7 @@ static void followpath_get_tars (bConstraint *con, ListBase *list) bConstraintTarget *ct; /* standard target-getting macro for single-target constraints without subtargets */ - SINGLETARGETNS_GET_TARS(con, data, ct, list) + SINGLETARGETNS_GET_TARS(con, data->tar, ct, list) } } @@ -1256,7 +1259,7 @@ static void followpath_flush_tars (bConstraint *con, ListBase *list, short nocop bConstraintTarget *ct= list->first; /* the following macro is used for all standard single-target constraints */ - SINGLETARGETNS_FLUSH_TARS(con, data, ct, list, nocopy) + SINGLETARGETNS_FLUSH_TARS(con, data->tar, ct, list, nocopy) } } @@ -1283,7 +1286,7 @@ static void followpath_get_tarmat (bConstraint *con, bConstraintOb *cob, bConstr if (cu->path && cu->path->data) { curvetime= bsystem_time(ct->tar, (float)ctime, 0.0) - data->offset; - + if (calc_ipo_spec(cu->ipo, CU_SPEED, &curvetime)==0) { curvetime /= cu->pathlen; CLAMP(curvetime, 0.0, 1.0); @@ -1546,7 +1549,7 @@ static void loclike_get_tars (bConstraint *con, ListBase *list) bConstraintTarget *ct; /* standard target-getting macro for single-target constraints */ - SINGLETARGET_GET_TARS(con, data, ct, list) + SINGLETARGET_GET_TARS(con, data->tar, data->subtarget, ct, list) } } @@ -1557,7 +1560,7 @@ static void loclike_flush_tars (bConstraint *con, ListBase *list, short nocopy) bConstraintTarget *ct= list->first; /* the following macro is used for all standard single-target constraints */ - SINGLETARGET_FLUSH_TARS(con, data, ct, list, nocopy) + SINGLETARGET_FLUSH_TARS(con, data->tar, data->subtarget, ct, list, nocopy) } } @@ -1661,7 +1664,7 @@ static void rotlike_get_tars (bConstraint *con, ListBase *list) bConstraintTarget *ct; /* standard target-getting macro for single-target constraints */ - SINGLETARGET_GET_TARS(con, data, ct, list) + SINGLETARGET_GET_TARS(con, data->tar, data->subtarget, ct, list) } } @@ -1672,7 +1675,7 @@ static void rotlike_flush_tars (bConstraint *con, ListBase *list, short nocopy) bConstraintTarget *ct= list->first; /* the following macro is used for all standard single-target constraints */ - SINGLETARGET_FLUSH_TARS(con, data, ct, list, nocopy) + SINGLETARGET_FLUSH_TARS(con, data->tar, data->subtarget, ct, list, nocopy) } } @@ -1749,7 +1752,7 @@ static void sizelike_get_tars (bConstraint *con, ListBase *list) bConstraintTarget *ct; /* standard target-getting macro for single-target constraints */ - SINGLETARGET_GET_TARS(con, data, ct, list) + SINGLETARGET_GET_TARS(con, data->tar, data->subtarget, ct, list) } } @@ -1760,7 +1763,7 @@ static void sizelike_flush_tars (bConstraint *con, ListBase *list, short nocopy) bConstraintTarget *ct= list->first; /* the following macro is used for all standard single-target constraints */ - SINGLETARGET_FLUSH_TARS(con, data, ct, list, nocopy) + SINGLETARGET_FLUSH_TARS(con, data->tar, data->subtarget, ct, list, nocopy) } } @@ -1928,7 +1931,7 @@ static void actcon_get_tars (bConstraint *con, ListBase *list) bConstraintTarget *ct; /* standard target-getting macro for single-target constraints */ - SINGLETARGET_GET_TARS(con, data, ct, list) + SINGLETARGET_GET_TARS(con, data->tar, data->subtarget, ct, list) } } @@ -1939,7 +1942,7 @@ static void actcon_flush_tars (bConstraint *con, ListBase *list, short nocopy) bConstraintTarget *ct= list->first; /* the following macro is used for all standard single-target constraints */ - SINGLETARGET_FLUSH_TARS(con, data, ct, list, nocopy) + SINGLETARGET_FLUSH_TARS(con, data->tar, data->subtarget, ct, list, nocopy) } } @@ -2068,7 +2071,7 @@ static void locktrack_get_tars (bConstraint *con, ListBase *list) bConstraintTarget *ct; /* the following macro is used for all standard single-target constraints */ - SINGLETARGET_GET_TARS(con, data, ct, list) + SINGLETARGET_GET_TARS(con, data->tar, data->subtarget, ct, list) } } @@ -2079,7 +2082,7 @@ static void locktrack_flush_tars (bConstraint *con, ListBase *list, short nocopy bConstraintTarget *ct= list->first; /* the following macro is used for all standard single-target constraints */ - SINGLETARGET_FLUSH_TARS(con, data, ct, list, nocopy) + SINGLETARGET_FLUSH_TARS(con, data->tar, data->subtarget, ct, list, nocopy) } } @@ -2419,7 +2422,7 @@ static void stretchto_get_tars (bConstraint *con, ListBase *list) bConstraintTarget *ct; /* standard target-getting macro for single-target constraints */ - SINGLETARGET_GET_TARS(con, data, ct, list) + SINGLETARGET_GET_TARS(con, data->tar, data->subtarget, ct, list) } } @@ -2430,7 +2433,7 @@ static void stretchto_flush_tars (bConstraint *con, ListBase *list, short nocopy bConstraintTarget *ct= list->first; /* the following macro is used for all standard single-target constraints */ - SINGLETARGET_FLUSH_TARS(con, data, ct, list, nocopy) + SINGLETARGET_FLUSH_TARS(con, data->tar, data->subtarget, ct, list, nocopy) } } @@ -2595,7 +2598,7 @@ static void minmax_get_tars (bConstraint *con, ListBase *list) bConstraintTarget *ct; /* standard target-getting macro for single-target constraints */ - SINGLETARGET_GET_TARS(con, data, ct, list) + SINGLETARGET_GET_TARS(con, data->tar, data->subtarget, ct, list) } } @@ -2606,7 +2609,7 @@ static void minmax_flush_tars (bConstraint *con, ListBase *list, short nocopy) bConstraintTarget *ct= list->first; /* the following macro is used for all standard single-target constraints */ - SINGLETARGET_FLUSH_TARS(con, data, ct, list, nocopy) + SINGLETARGET_FLUSH_TARS(con, data->tar, data->subtarget, ct, list, nocopy) } } @@ -2725,7 +2728,7 @@ static void rbj_get_tars (bConstraint *con, ListBase *list) bConstraintTarget *ct; /* standard target-getting macro for single-target constraints without subtargets */ - SINGLETARGETNS_GET_TARS(con, data, ct, list) + SINGLETARGETNS_GET_TARS(con, data->tar, ct, list) } } @@ -2736,7 +2739,7 @@ static void rbj_flush_tars (bConstraint *con, ListBase *list, short nocopy) bConstraintTarget *ct= list->first; /* the following macro is used for all standard single-target constraints */ - SINGLETARGETNS_FLUSH_TARS(con, data, ct, list, nocopy) + SINGLETARGETNS_FLUSH_TARS(con, data->tar, ct, list, nocopy) } } @@ -2764,7 +2767,7 @@ static void clampto_get_tars (bConstraint *con, ListBase *list) bConstraintTarget *ct; /* standard target-getting macro for single-target constraints without subtargets */ - SINGLETARGETNS_GET_TARS(con, data, ct, list) + SINGLETARGETNS_GET_TARS(con, data->tar, ct, list) } } @@ -2775,7 +2778,7 @@ static void clampto_flush_tars (bConstraint *con, ListBase *list, short nocopy) bConstraintTarget *ct= list->first; /* the following macro is used for all standard single-target constraints */ - SINGLETARGETNS_FLUSH_TARS(con, data, ct, list, nocopy) + SINGLETARGETNS_FLUSH_TARS(con, data->tar, ct, list, nocopy) } } @@ -2937,7 +2940,7 @@ static void transform_get_tars (bConstraint *con, ListBase *list) bConstraintTarget *ct; /* standard target-getting macro for single-target constraints */ - SINGLETARGET_GET_TARS(con, data, ct, list) + SINGLETARGET_GET_TARS(con, data->tar, data->subtarget, ct, list) } } @@ -2948,7 +2951,7 @@ static void transform_flush_tars (bConstraint *con, ListBase *list, short nocopy bConstraintTarget *ct= list->first; /* the following macro is used for all standard single-target constraints */ - SINGLETARGET_FLUSH_TARS(con, data, ct, list, nocopy) + SINGLETARGET_FLUSH_TARS(con, data->tar, data->subtarget, ct, list, nocopy) } } @@ -3225,7 +3228,7 @@ void copy_constraints (ListBase *dst, ListBase *src) * None of the actual calculations of the matricies should be done here! Also, this function is * not to be used by any new constraints, particularly any that have multiple targets. */ -void get_constraint_target_matrix (bConstraint *con, short ownertype, void *ownerdata, float mat[][4], float ctime) +void get_constraint_target_matrix (bConstraint *con, int n, short ownertype, void *ownerdata, float mat[][4], float ctime) { bConstraintTypeInfo *cti= constraint_get_typeinfo(con); ListBase targets = {NULL, NULL}; @@ -3272,6 +3275,9 @@ void get_constraint_target_matrix (bConstraint *con, short ownertype, void *owne /* only calculate the target matrix on the first target */ ct= (bConstraintTarget *)targets.first; + while(ct && n-- > 0) + ct= ct->next; + if (ct) { if (cti->get_target_matrix) cti->get_target_matrix(con, cob, ct, ctime); |