forked from bartvdbraak/blender
Action constraint works again. Needs revision though... do that with
testfiles i get from Bassam. :) Further removed old code that was ifdeffed hanging around still.
This commit is contained in:
parent
a4e959b369
commit
4fb314b809
@ -799,12 +799,23 @@ static void execute_posechain(Object *ob, PoseChain *chain)
|
||||
/* not yet free! */
|
||||
}
|
||||
|
||||
void free_posechain (PoseChain *chain)
|
||||
{
|
||||
if (chain->solver) {
|
||||
MEM_freeN (chain->solver->segments);
|
||||
chain->solver->segments = NULL;
|
||||
IK_FreeChain(chain->solver);
|
||||
}
|
||||
if(chain->pchanchain) MEM_freeN(chain->pchanchain);
|
||||
MEM_freeN(chain);
|
||||
}
|
||||
|
||||
/* ********************** THE POSE SOLVER ******************* */
|
||||
|
||||
|
||||
/* loc/rot/size to mat4 */
|
||||
static void chan_calc_mat(bPoseChannel *chan)
|
||||
/* used in constraint.c too */
|
||||
void chan_calc_mat(bPoseChannel *chan)
|
||||
{
|
||||
float smat[3][3];
|
||||
float rmat[3][3];
|
||||
@ -820,7 +831,8 @@ static void chan_calc_mat(bPoseChannel *chan)
|
||||
Mat4CpyMat3(chan->chan_mat, tmat);
|
||||
|
||||
/* prevent action channels breaking chains */
|
||||
if (!(chan->bone->flag & BONE_IK_TOPARENT)) {
|
||||
/* need to check for bone here, CONSTRAINT_TYPE_ACTION uses this call */
|
||||
if (chan->bone==NULL || !(chan->bone->flag & BONE_IK_TOPARENT)) {
|
||||
VECCOPY(chan->chan_mat[3], chan->loc);
|
||||
}
|
||||
|
||||
@ -926,7 +938,7 @@ static void where_is_pose_bone(Object *ob, bPoseChannel *pchan)
|
||||
//VECCOPY(conOb.size, pchan->size); // stretchto constraint
|
||||
|
||||
/* Solve */
|
||||
solve_constraints (&conOb, TARGET_BONE, (void*)bone, ctime); // ctime doesnt alter objects
|
||||
solve_constraints (&conOb, TARGET_BONE, (void*)pchan, ctime); // ctime doesnt alter objects
|
||||
|
||||
//VECCOPY(bone->size, conOb.size); // stretchto constraint
|
||||
|
||||
@ -1015,20 +1027,7 @@ void where_is_pose (Object *ob)
|
||||
else where_is_pose_bone(ob, pchan);
|
||||
}
|
||||
}
|
||||
//#endif
|
||||
}
|
||||
|
||||
#if 0
|
||||
doconstraints= 1;
|
||||
for(pchan= ob->pose->chanbase.first; pchan; pchan= pchan->next) {
|
||||
where_is_pose_bone(ob, pchan);
|
||||
}
|
||||
doconstraints= 0;
|
||||
for(pchan= ob->pose->chanbase.first; pchan; pchan= pchan->next) {
|
||||
where_is_pose_bone(ob, pchan);
|
||||
pchan->flag &= ~POSE_IK_MAT;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* calculating deform matrices */
|
||||
for(pchan= ob->pose->chanbase.first; pchan; pchan= next) {
|
||||
@ -1061,214 +1060,3 @@ Bone *get_indexed_bone (Object *ob, int index)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
/* *********************** Inverse Kinematics ************* */
|
||||
|
||||
#if 0
|
||||
void solve_posechain (PoseChain *chain)
|
||||
{
|
||||
float goal[3];
|
||||
int i;
|
||||
Bone *curBone;
|
||||
// float M_obmat[4][4];
|
||||
// float M_basischange[4][4];
|
||||
bPoseChannel *chan;
|
||||
|
||||
if (!chain->solver) return;
|
||||
|
||||
/**
|
||||
* Transform the goal from worldspace
|
||||
* to the coordinate system of the root
|
||||
* of the chain. The matrix for this
|
||||
* was computed when the chain was built
|
||||
* in ik_chain_to_posechain
|
||||
*/
|
||||
|
||||
VECCOPY (goal, chain->goal);
|
||||
Mat4MulVecfl (chain->goalinv, goal);
|
||||
/* Solve the chain */
|
||||
|
||||
IK_SolveChain(chain->solver,
|
||||
goal,
|
||||
chain->tolerance,
|
||||
chain->iterations,
|
||||
0.1f,
|
||||
chain->solver->segments);
|
||||
|
||||
/* Copy the results back into the bones */
|
||||
for (i = chain->solver->num_segments-1, curBone=chain->target->parent; i>=0; i--, curBone=curBone->parent){
|
||||
// for (i = 0; i<chain->solver->num_segments; i++) {
|
||||
//curBone= bonelist[i];
|
||||
|
||||
/* Retrieve the delta rotation from the solver */
|
||||
// Mat4One(M_basischange);
|
||||
// Mat4CpyMat3(M_basischange, (void *)chain->solver->segments[i].basis_change); //basis_change = array[9]
|
||||
// printmatrix3(curBone->name, (void *)chain->solver->segments[i].basis_change);
|
||||
/**
|
||||
* Multiply the bone's usertransform by the
|
||||
* basis change to get the new usertransform
|
||||
*/
|
||||
|
||||
//Mat4CpyMat4 (M_obmat, curBone->obmat);
|
||||
//Mat4MulMat4 (curBone->obmat, M_basischange, M_obmat);
|
||||
/* store in channel itself */
|
||||
|
||||
chan= get_pose_channel(chain->pose, curBone->name);
|
||||
Mat3CpyMat3 (chan->ik_mat, (void *)chain->solver->segments[i].basis_change);
|
||||
chan->flag |= POSE_IK_MAT;
|
||||
|
||||
/* Store the solve results on the childrens' channels */
|
||||
//for (chan = chain->pose->chanbase.first; chan; chan=chan->next){
|
||||
// if (!strcmp (chan->name, curBone->name)){
|
||||
// Mat4CpyMat4 (chan->obmat, curBone->obmat);
|
||||
// break;
|
||||
// }
|
||||
//}
|
||||
}
|
||||
/* WARNING! REMOVE LATER !!! */
|
||||
/* flag chain target to recalculate too */
|
||||
chan= get_pose_channel(chain->pose, chain->target->name);
|
||||
Mat3One(chan->ik_mat);
|
||||
chan->flag |= POSE_IK_MAT;
|
||||
}
|
||||
#endif
|
||||
|
||||
void free_posechain (PoseChain *chain)
|
||||
{
|
||||
if (chain->solver) {
|
||||
MEM_freeN (chain->solver->segments);
|
||||
chain->solver->segments = NULL;
|
||||
IK_FreeChain(chain->solver);
|
||||
}
|
||||
if(chain->pchanchain) MEM_freeN(chain->pchanchain);
|
||||
MEM_freeN(chain);
|
||||
}
|
||||
|
||||
#if 0
|
||||
/* actually; bones to IK_solver data */
|
||||
/* Object is its own Armature object */
|
||||
PoseChain *ik_chain_to_posechain (Object *ob, Bone *bone)
|
||||
{
|
||||
IK_Segment_Extern *segs;
|
||||
PoseChain *chain = NULL;
|
||||
Bone *curBone, *rootBone;
|
||||
int segcount, curseg, icurseg;
|
||||
float imat[4][4];
|
||||
bPoseChannel *pchan;
|
||||
Bone *bonelist[256];
|
||||
float rootmat[4][4];
|
||||
// float bonespace[4][4];
|
||||
|
||||
/**
|
||||
* Some interesting variables in this function:
|
||||
*
|
||||
* Bone->obmat Bone's user transformation;
|
||||
* It is initialized in where_is_b one1_time
|
||||
*
|
||||
* rootmat Bone's coordinate system, computed by
|
||||
* get_objectspace_bone_matrix. Takes all
|
||||
* parents transformations into account.
|
||||
*/
|
||||
|
||||
|
||||
|
||||
/* Ensure that all of the bone parent matrices are correct */
|
||||
|
||||
/* Find the chain's root & count the segments needed */
|
||||
segcount = 0;
|
||||
for (curBone = bone; curBone; curBone=curBone->parent){
|
||||
rootBone = curBone;
|
||||
if (curBone!=bone){
|
||||
bonelist[segcount]=curBone;
|
||||
segcount++;
|
||||
}
|
||||
if (!curBone->parent)
|
||||
break;
|
||||
else if (!(curBone->flag & BONE_IK_TOPARENT))
|
||||
break;
|
||||
}
|
||||
|
||||
if (!segcount)
|
||||
return NULL;
|
||||
|
||||
|
||||
/**
|
||||
* Initialize a record to store information about the original bones
|
||||
* This will be the return value for this function.
|
||||
*/
|
||||
|
||||
chain = MEM_callocN(sizeof(PoseChain), "posechain");
|
||||
chain->solver = IK_CreateChain();
|
||||
chain->target = bone;
|
||||
chain->root = rootBone;
|
||||
chain->pose = ob->pose;
|
||||
|
||||
/* Allocate some IK segments */
|
||||
segs = MEM_callocN (sizeof(IK_Segment_Extern)*segcount, "iksegments");
|
||||
|
||||
//printf("segcount %d\n", segcount);
|
||||
/**
|
||||
* Remove the offset from the first bone in the chain and take the target to chainspace
|
||||
*/
|
||||
|
||||
//get_objectspace_bone_matrix(rootBone, bonespace, 1, 1);
|
||||
//Mat4One (rootmat);
|
||||
//VECCOPY (rootmat[3], bonespace[3]);
|
||||
pchan= get_pose_channel(ob->pose, rootBone->name);
|
||||
Mat4One(rootmat);
|
||||
VECCOPY(rootmat[3], pchan->pose_head);
|
||||
|
||||
/* Take the target to bonespace */
|
||||
/* (ton) I think it's the matrix to take a world coordinate into "chainspace" */
|
||||
Mat4MulMat4 (imat, rootmat, ob->obmat);
|
||||
Mat4Invert (chain->goalinv, imat);
|
||||
|
||||
/**
|
||||
* Build matrices from the root to the tip
|
||||
* We count backwards through the bone list (which is sorted tip to root)
|
||||
* and forwards through the ik_segment list
|
||||
*/
|
||||
/* that we're going to recode! (ton) */
|
||||
for (curseg = segcount-1; curseg>=0; curseg--){
|
||||
float M_basismat[4][4];
|
||||
float R_parmat[4][4];
|
||||
float iR_parmat[4][4];
|
||||
float R_bonemat[4][4];
|
||||
|
||||
/* Retrieve the corresponding bone for this segment */
|
||||
icurseg=segcount-curseg-1;
|
||||
curBone = bonelist[curseg];
|
||||
|
||||
/* Get the basis matrix */
|
||||
Mat4One (R_parmat);
|
||||
//get_objectspace_bone_matrix(curBone, R_bonemat, 1, 1);
|
||||
//R_bonemat[3][0]=R_bonemat[3][1]=R_bonemat[3][2]=0.0F;
|
||||
pchan= get_pose_channel(ob->pose, curBone->name);
|
||||
Mat4CpyMat4(R_bonemat, pchan->pose_mat);
|
||||
R_bonemat[3][0]=R_bonemat[3][1]=R_bonemat[3][2]=0.0F;
|
||||
|
||||
if (curBone->parent && (curBone->flag & BONE_IK_TOPARENT)) {
|
||||
//get_objectspace_bone_matrix(curBone->parent, R_parmat, 1, 1);
|
||||
Mat4CpyMat4(R_parmat, pchan->parent->pose_mat);
|
||||
|
||||
R_parmat[3][0]=R_parmat[3][1]=R_parmat[3][2]=0.0F;
|
||||
}
|
||||
|
||||
Mat4Invert(iR_parmat, R_parmat);
|
||||
Mat4MulMat4(M_basismat, R_bonemat, iR_parmat);
|
||||
|
||||
/* Copy the matrix into the basis and transpose */
|
||||
Mat3CpyMat4((void *)segs[icurseg].basis, M_basismat); // basis = array[9]
|
||||
Mat3Transp((void *)segs[icurseg].basis);
|
||||
|
||||
/* Fill out the IK segment */
|
||||
segs[icurseg].length = VecLenf(curBone->head, curBone->tail);
|
||||
|
||||
}
|
||||
|
||||
IK_LoadChain(chain->solver, segs, segcount);
|
||||
|
||||
return chain;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
@ -687,6 +687,7 @@ static void constraint_target_to_mat4 (Object *ob, const char *substring, float
|
||||
|
||||
/* called during solve_constraints */
|
||||
/* also for make_parent, to find correct inverse of "follow path" */
|
||||
/* warning, ownerdata is void... is not Bone anymore, but posechannel */
|
||||
short get_constraint_target_matrix (bConstraint *con, short ownertype, void* ownerdata, float mat[][4], float size[3], float ctime)
|
||||
{
|
||||
short valid=0;
|
||||
@ -699,45 +700,29 @@ short get_constraint_target_matrix (bConstraint *con, short ownertype, void* own
|
||||
break;
|
||||
case CONSTRAINT_TYPE_ACTION:
|
||||
{
|
||||
if (ownertype == TARGET_BONE){
|
||||
if (ownertype == TARGET_BONE) {
|
||||
extern void chan_calc_mat(bPoseChannel *chan);
|
||||
bActionConstraint *data = (bActionConstraint*)con->data;
|
||||
bPose *pose=NULL;
|
||||
bPoseChannel *pchan=NULL;
|
||||
float tempmat[4][4], imat[4][4], ans[4][4], restmat[4][4], irestmat[4][4];
|
||||
bPoseChannel *pchan, *tchan;
|
||||
float ans[4][4];
|
||||
float tempmat3[3][3];
|
||||
float eul[3], size[3];
|
||||
float eul[3];
|
||||
float s,t;
|
||||
Bone *curBone;
|
||||
Bone tbone;
|
||||
// int i;
|
||||
|
||||
curBone = (Bone*)ownerdata;
|
||||
Mat4One(mat);
|
||||
|
||||
if (data->tar){
|
||||
constraint_target_to_mat4(data->tar, data->subtarget, tempmat, size, ctime);
|
||||
valid=1;
|
||||
if (data->tar==NULL) return 0;
|
||||
|
||||
/* proper check for bone... (todo) */
|
||||
if(data->subtarget[0]) {
|
||||
//pchan = get_pose_channel(ob->pose, substring);
|
||||
//if (pchan) {
|
||||
//}
|
||||
}
|
||||
else
|
||||
Mat4One (tempmat);
|
||||
|
||||
/* If this is a bone, undo parent transforms */
|
||||
if (strlen(data->subtarget)){
|
||||
Bone* bone;
|
||||
|
||||
Mat4Invert(imat, data->tar->obmat);
|
||||
bone = get_named_bone(get_armature(data->tar), data->subtarget);
|
||||
if (bone){
|
||||
get_objectspace_bone_matrix(bone, restmat, 1, 0);
|
||||
Mat4Invert(irestmat, restmat);
|
||||
}
|
||||
}
|
||||
else{
|
||||
Mat4One(imat);
|
||||
Mat4One(irestmat);
|
||||
}
|
||||
|
||||
Mat4MulSerie(ans, imat, tempmat, irestmat, NULL, NULL, NULL, NULL, NULL);
|
||||
constraint_target_to_mat4(data->tar, data->subtarget, ans, size, ctime);
|
||||
|
||||
/* extract rotation */
|
||||
Mat3CpyMat4(tempmat3, ans);
|
||||
Mat3ToEul(tempmat3, eul);
|
||||
|
||||
@ -745,7 +730,7 @@ short get_constraint_target_matrix (bConstraint *con, short ownertype, void* own
|
||||
eul[1]*=(float)(180.0/M_PI);
|
||||
eul[2]*=(float)(180.0/M_PI);
|
||||
|
||||
/* Target is the animation */
|
||||
/* Target defines the animation */
|
||||
s = (eul[data->type]-data->min)/(data->max-data->min);
|
||||
if (s<0)
|
||||
s=0;
|
||||
@ -753,29 +738,18 @@ short get_constraint_target_matrix (bConstraint *con, short ownertype, void* own
|
||||
s=1;
|
||||
|
||||
t = ( s * (data->end-data->start)) + data->start;
|
||||
|
||||
/* Get the appropriate information from the action */
|
||||
|
||||
/* Get the appropriate information from the action, we make temp pose */
|
||||
pose = MEM_callocN(sizeof(bPose), "pose");
|
||||
|
||||
verify_pose_channel(pose, curBone->name);
|
||||
pchan = ownerdata;
|
||||
tchan= verify_pose_channel(pose, pchan->name);
|
||||
extract_pose_from_action (pose, data->act, t);
|
||||
|
||||
chan_calc_mat(tchan);
|
||||
|
||||
Mat4CpyMat4(mat, tchan->chan_mat);
|
||||
|
||||
/* Find the appropriate channel */
|
||||
pchan = get_pose_channel(pose, curBone->name);
|
||||
if (pchan){
|
||||
memset(&tbone, 0x00, sizeof(Bone));
|
||||
|
||||
// VECCOPY (tbone.loc, pchan->loc);
|
||||
// VECCOPY (tbone.size, pchan->size);
|
||||
// for (i=0; i<4; i++)
|
||||
// tbone.quat[i]=pchan->quat[i];
|
||||
//
|
||||
// bone_to_mat4(&tbone, mat);
|
||||
|
||||
}
|
||||
else{
|
||||
Mat4One(mat);
|
||||
}
|
||||
/* Clean up */
|
||||
free_pose_channels(pose);
|
||||
MEM_freeN(pose);
|
||||
@ -1029,79 +1003,7 @@ void evaluate_constraint (bConstraint *constraint, Object *ob, short ownertype,
|
||||
break;
|
||||
case CONSTRAINT_TYPE_KINEMATIC:
|
||||
{
|
||||
#if 0
|
||||
bKinematicConstraint *data;
|
||||
float imat[4][4];
|
||||
float temp[4][4];
|
||||
float totmat[4][4];
|
||||
|
||||
data=(bKinematicConstraint*)constraint->data;
|
||||
|
||||
if (data->tar && ownertype==TARGET_BONE && ownerdata){
|
||||
Bone *curBone = (Bone*)ownerdata;
|
||||
PoseChain *chain;
|
||||
Object *armob;
|
||||
|
||||
/* Retrieve the owner armature object from the workob */
|
||||
armob = ob->parent;
|
||||
|
||||
/* Make an IK chain */
|
||||
chain = ik_chain_to_posechain(armob, curBone);
|
||||
if (!chain)
|
||||
return;
|
||||
chain->iterations = data->iterations;
|
||||
chain->tolerance = data->tolerance;
|
||||
|
||||
|
||||
if(0) {
|
||||
bPoseChannel *pchan= get_pose_channel(armob->pose, curBone->name);
|
||||
float parmat[4][4];
|
||||
|
||||
/* Take the obmat to objectspace */
|
||||
|
||||
// Mat4CpyMat4 (temp, curBone->obmat);
|
||||
// Mat4One (curBone->obmat);
|
||||
// get_objectspace_bone_matrix(curBone, parmat, 1, 1);
|
||||
Mat4CpyMat4(parmat, pchan->pose_mat);
|
||||
|
||||
// Mat4CpyMat4 (curBone->obmat, temp);
|
||||
Mat4MulMat4 (totmat, parmat, armob->obmat);
|
||||
|
||||
Mat4Invert (imat, totmat);
|
||||
|
||||
Mat4CpyMat4 (temp, ob->obmat);
|
||||
Mat4MulMat4 (ob->obmat, temp, imat);
|
||||
}
|
||||
|
||||
|
||||
/* Solve it */
|
||||
if (chain->solver){
|
||||
VECCOPY (chain->goal, targetmat[3]);
|
||||
solve_posechain(chain); // applies to bones/channels
|
||||
}
|
||||
|
||||
free_posechain(chain);
|
||||
|
||||
if(0) {
|
||||
float parmat[4][4];
|
||||
bPoseChannel *pchan= get_pose_channel(armob->pose, curBone->name);
|
||||
|
||||
/* Take the obmat to worldspace */
|
||||
// Mat4CpyMat4 (temp, curBone->obmat);
|
||||
// Mat4One (curBone->obmat);
|
||||
|
||||
// get_objectspace_bone_matrix(curBone, parmat, 1, 1);
|
||||
Mat4CpyMat4(parmat, pchan->pose_mat);
|
||||
|
||||
// Mat4CpyMat4 (curBone->obmat, temp);
|
||||
Mat4MulMat4 (totmat, parmat, armob->obmat);
|
||||
|
||||
Mat4CpyMat4 (temp, ob->obmat);
|
||||
Mat4MulMat4 (ob->obmat, temp, totmat);
|
||||
|
||||
}
|
||||
}
|
||||
#endif
|
||||
/* removed */
|
||||
}
|
||||
break;
|
||||
case CONSTRAINT_TYPE_LOCKTRACK:
|
||||
|
@ -1095,7 +1095,7 @@ void ob_parbone(Object *ob, Object *par, float mat[][4])
|
||||
/* Make sure the bone is still valid */
|
||||
pchan= get_pose_channel(par->pose, ob->parsubstr);
|
||||
if (!pchan){
|
||||
printf ("Lost bone %s\n", ob->parsubstr);
|
||||
printf ("Bone parent: no bone %s\n", ob->parsubstr);
|
||||
Mat4One(mat);
|
||||
return;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user