diff --git a/source/blender/blenkernel/intern/armature.c b/source/blender/blenkernel/intern/armature.c index 61122610e50..b424a057cf0 100644 --- a/source/blender/blenkernel/intern/armature.c +++ b/source/blender/blenkernel/intern/armature.c @@ -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; isolver->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 diff --git a/source/blender/blenkernel/intern/constraint.c b/source/blender/blenkernel/intern/constraint.c index f373c7f9062..800940ae5c4 100644 --- a/source/blender/blenkernel/intern/constraint.c +++ b/source/blender/blenkernel/intern/constraint.c @@ -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: diff --git a/source/blender/blenkernel/intern/object.c b/source/blender/blenkernel/intern/object.c index 68aa863d22c..a2c0e9241db 100644 --- a/source/blender/blenkernel/intern/object.c +++ b/source/blender/blenkernel/intern/object.c @@ -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; }