diff options
author | Benoit Bolsee <benoit.bolsee@online.be> | 2009-09-25 01:22:24 +0400 |
---|---|---|
committer | Benoit Bolsee <benoit.bolsee@online.be> | 2009-09-25 01:22:24 +0400 |
commit | 1483fafd1372a3d3e025d08634e798adb7da512f (patch) | |
tree | 9191765749e29866339f4c31d892603f5f8b334d /source/blender/blenkernel | |
parent | c995c605f640d8d688e6e58e0fe247ca83f91696 (diff) | |
parent | 222fe6b1a5d49f67177cbb762f55a0e482145f5d (diff) |
Merge of itasc branch. Project files, scons and cmake should be working. Makefile updated but not tested. Comes with Eigen2 2.0.6 C++ matrix library.
Diffstat (limited to 'source/blender/blenkernel')
-rw-r--r-- | source/blender/blenkernel/BKE_action.h | 23 | ||||
-rw-r--r-- | source/blender/blenkernel/BKE_armature.h | 6 | ||||
-rw-r--r-- | source/blender/blenkernel/BKE_constraint.h | 6 | ||||
-rw-r--r-- | source/blender/blenkernel/CMakeLists.txt | 2 | ||||
-rw-r--r-- | source/blender/blenkernel/SConscript | 2 | ||||
-rw-r--r-- | source/blender/blenkernel/intern/Makefile | 1 | ||||
-rw-r--r-- | source/blender/blenkernel/intern/action.c | 185 | ||||
-rw-r--r-- | source/blender/blenkernel/intern/armature.c | 486 | ||||
-rw-r--r-- | source/blender/blenkernel/intern/constraint.c | 3 | ||||
-rw-r--r-- | source/blender/blenkernel/intern/pointcache.c | 4 | ||||
-rw-r--r-- | source/blender/blenkernel/intern/sca.c | 18 |
11 files changed, 117 insertions, 619 deletions
diff --git a/source/blender/blenkernel/BKE_action.h b/source/blender/blenkernel/BKE_action.h index f079cc08281..17b56864d1e 100644 --- a/source/blender/blenkernel/BKE_action.h +++ b/source/blender/blenkernel/BKE_action.h @@ -41,6 +41,7 @@ struct bAction; struct bActionGroup; struct FCurve; struct bPose; +struct bItasc; struct bPoseChannel; struct Object; struct Scene; @@ -154,11 +155,21 @@ struct bPoseChannel *get_active_posechannel(struct Object *ob); */ struct bPoseChannel *verify_pose_channel(struct bPose* pose, const char* name); - +/* Copy the data from the action-pose (src) into the pose */ +void extract_pose_from_pose(struct bPose *pose, const struct bPose *src); /* sets constraint flags */ void update_pose_constraint_flags(struct bPose *pose); +/* return the name of structure pointed by pose->ikparam */ +const char *get_ikparam_name(struct bPose *pose); + +/* allocate and initialize pose->ikparam according to pose->iksolver */ +void init_pose_ikparam(struct bPose *pose); + +/* initialize a bItasc structure with default value */ +void init_pose_itasc(struct bItasc *itasc); + /* clears BONE_UNKEYED flags for frame changing */ // XXX to be depreceated for a more general solution in animsys... void framechange_poses_clear_unkeyed(void); @@ -181,16 +192,6 @@ void copy_pose_result(struct bPose *to, struct bPose *from); /* clear all transforms */ void rest_pose(struct bPose *pose); -/* Game Engine ------------------------- */ - -/* exported for game engine */ -void game_blend_poses(struct bPose *dst, struct bPose *src, float srcweight/*, short mode*/); /* was blend_poses */ -void extract_pose_from_pose(struct bPose *pose, const struct bPose *src); - -/* functions used by the game engine */ -void game_copy_pose(struct bPose **dst, struct bPose *src); -void game_free_pose(struct bPose *pose); - #ifdef __cplusplus }; #endif diff --git a/source/blender/blenkernel/BKE_armature.h b/source/blender/blenkernel/BKE_armature.h index 1cbb2331782..8dbd2721fb9 100644 --- a/source/blender/blenkernel/BKE_armature.h +++ b/source/blender/blenkernel/BKE_armature.h @@ -89,6 +89,7 @@ void where_is_armature (struct bArmature *arm); void where_is_armature_bone(struct Bone *bone, struct Bone *prevbone); void armature_rebuild_pose(struct Object *ob, struct bArmature *arm); void where_is_pose (struct Scene *scene, struct Object *ob); +void where_is_pose_bone(struct Scene *scene, struct Object *ob, struct bPoseChannel *pchan, float ctime); /* get_objectspace_bone_matrix has to be removed still */ void get_objectspace_bone_matrix (struct Bone* bone, float M_accumulatedMatrix[][4], int root, int posed); @@ -102,11 +103,6 @@ void armature_mat_pose_to_bone(struct bPoseChannel *pchan, float inmat[][4], flo void armature_loc_pose_to_bone(struct bPoseChannel *pchan, float *inloc, float *outloc); void armature_mat_pose_to_delta(float delta_mat[][4], float pose_mat[][4], float arm_mat[][4]); -/* Animation functions */ -struct PoseTree *ik_tree_to_posetree(struct Object *ob, struct Bone *bone); -void solve_posetree(PoseTree *tree); -void free_posetree(PoseTree *tree); - /* B-Bone support */ typedef struct Mat4 { float mat[4][4]; diff --git a/source/blender/blenkernel/BKE_constraint.h b/source/blender/blenkernel/BKE_constraint.h index a0061173438..126816f5a95 100644 --- a/source/blender/blenkernel/BKE_constraint.h +++ b/source/blender/blenkernel/BKE_constraint.h @@ -38,6 +38,9 @@ struct Scene; struct bPoseChannel; /* ---------------------------------------------------------------------------- */ +#ifdef __cplusplus +extern "C" { +#endif /* special struct for use in constraint evaluation */ typedef struct bConstraintOb { @@ -131,6 +134,9 @@ void constraint_mat_convertspace(struct Object *ob, struct bPoseChannel *pchan, void get_constraint_target_matrix(struct bConstraint *con, int n, short ownertype, void *ownerdata, float mat[][4], float ctime); void solve_constraints(struct ListBase *conlist, struct bConstraintOb *cob, float ctime); +#ifdef __cplusplus +} +#endif #endif diff --git a/source/blender/blenkernel/CMakeLists.txt b/source/blender/blenkernel/CMakeLists.txt index 68aed2b0184..3473950ab3a 100644 --- a/source/blender/blenkernel/CMakeLists.txt +++ b/source/blender/blenkernel/CMakeLists.txt @@ -30,7 +30,7 @@ SET(INC . ../../../intern/guardedalloc ../../../intern/memutil ../editors/include ../blenlib ../makesdna ../render/extern/include ../../../intern/decimation/extern ../imbuf ../avi ../../../intern/elbeem/extern ../../../intern/opennl/extern - ../../../intern/iksolver/extern ../blenloader + ../../../intern/iksolver/extern ../blenloader ../ikplugin ../nodes ../../../extern/glew/include ../gpu ../makesrna ../../../intern/smoke/extern ../../../intern/bsp/extern ../blenfont ../../../intern/audaspace/intern diff --git a/source/blender/blenkernel/SConscript b/source/blender/blenkernel/SConscript index 1f42390504d..944667e2963 100644 --- a/source/blender/blenkernel/SConscript +++ b/source/blender/blenkernel/SConscript @@ -5,7 +5,7 @@ sources = env.Glob('intern/*.c') incs = '. #/intern/guardedalloc #/intern/memutil ../editors/include ../blenlib ../blenfont ../makesdna' incs += ' ../render/extern/include #/intern/decimation/extern ../makesrna' -incs += ' ../imbuf ../avi #/intern/elbeem/extern ../nodes' +incs += ' ../imbuf ../ikplugin ../avi #/intern/elbeem/extern ../nodes' incs += ' #/intern/iksolver/extern ../blenloader' incs += ' #/extern/bullet2/src' incs += ' #/intern/opennl/extern #/intern/bsp/extern' diff --git a/source/blender/blenkernel/intern/Makefile b/source/blender/blenkernel/intern/Makefile index 6c2edc9e25f..f16b57c8469 100644 --- a/source/blender/blenkernel/intern/Makefile +++ b/source/blender/blenkernel/intern/Makefile @@ -47,6 +47,7 @@ CPPFLAGS += -I$(NAN_AUDASPACE)/include CPPFLAGS += -I../../makesdna CPPFLAGS += -I../../makesrna CPPFLAGS += -I../../imbuf +CPPFLAGS += -I../../ikplugin # This mod uses the BLI and BLO module CPPFLAGS += -I../../blenlib CPPFLAGS += -I../../blenloader diff --git a/source/blender/blenkernel/intern/action.c b/source/blender/blenkernel/intern/action.c index 1ff5d9b5c01..4cfd35a494d 100644 --- a/source/blender/blenkernel/intern/action.c +++ b/source/blender/blenkernel/intern/action.c @@ -62,6 +62,7 @@ #include "BKE_main.h" #include "BKE_object.h" #include "BKE_utildefines.h" +#include "BIK_api.h" #include "BLI_arithb.h" #include "BLI_blenlib.h" @@ -451,7 +452,7 @@ bPoseChannel *verify_pose_channel(bPose* pose, const char* name) chan->limitmin[0]= chan->limitmin[1]= chan->limitmin[2]= -180.0f; chan->limitmax[0]= chan->limitmax[1]= chan->limitmax[2]= 180.0f; chan->stiffness[0]= chan->stiffness[1]= chan->stiffness[2]= 0.0f; - + chan->ikrotweight = chan->iklinweight = 0.0f; Mat4One(chan->constinv); BLI_addtail(&pose->chanbase, chan); @@ -477,7 +478,18 @@ bPoseChannel *get_active_posechannel (Object *ob) return NULL; } - +const char *get_ikparam_name(bPose *pose) +{ + if (pose) { + switch (pose->iksolver) { + case IKSOLVER_LEGACY: + return NULL; + case IKSOLVER_ITASC: + return "bItasc"; + } + } + return NULL; +} /* dst should be freed already, makes entire duplicate */ void copy_pose (bPose **dst, bPose *src, int copycon) { @@ -499,7 +511,10 @@ void copy_pose (bPose **dst, bPose *src, int copycon) outPose= MEM_callocN(sizeof(bPose), "pose"); BLI_duplicatelist(&outPose->chanbase, &src->chanbase); - + outPose->iksolver = src->iksolver; + outPose->ikdata = NULL; + outPose->ikparam = MEM_dupallocN(src->ikparam); + if (copycon) { for (pchan=outPose->chanbase.first; pchan; pchan=pchan->next) { copy_constraints(&listb, &pchan->constraints); // copy_constraints NULLs listb @@ -511,6 +526,39 @@ void copy_pose (bPose **dst, bPose *src, int copycon) *dst=outPose; } +void init_pose_itasc(bItasc *itasc) +{ + if (itasc) { + itasc->iksolver = IKSOLVER_ITASC; + itasc->minstep = 0.01f; + itasc->maxstep = 0.06f; + itasc->numiter = 100; + itasc->numstep = 4; + itasc->precision = 0.005f; + itasc->flag = ITASC_AUTO_STEP|ITASC_INITIAL_REITERATION|ITASC_SIMULATION; + itasc->feedback = 20.f; + itasc->maxvel = 50.f; + itasc->solver = ITASC_SOLVER_SDLS; + itasc->dampmax = 0.5; + itasc->dampeps = 0.15; + } +} +void init_pose_ikparam(bPose *pose) +{ + bItasc *itasc; + switch (pose->iksolver) { + case IKSOLVER_ITASC: + itasc = MEM_callocN(sizeof(bItasc), "itasc"); + init_pose_itasc(itasc); + pose->ikparam = itasc; + break; + case IKSOLVER_LEGACY: + default: + pose->ikparam = NULL; + break; + } +} + void free_pose_channels(bPose *pose) { bPoseChannel *pchan; @@ -534,133 +582,15 @@ void free_pose(bPose *pose) /* free pose-groups */ if (pose->agroups.first) BLI_freelistN(&pose->agroups); - - /* free pose */ - MEM_freeN(pose); - } -} - -void game_copy_pose(bPose **dst, bPose *src) -{ - bPose *out; - bPoseChannel *pchan, *outpchan; - GHash *ghash; - - /* the game engine copies the current armature pose and then swaps - * the object pose pointer. this makes it possible to change poses - * without affecting the original blender data. */ - - if (!src) { - *dst=NULL; - return; - } - else if (*dst==src) { - printf("copy_pose source and target are the same\n"); - *dst=NULL; - return; - } - - out= MEM_dupallocN(src); - out->agroups.first= out->agroups.last= NULL; - BLI_duplicatelist(&out->chanbase, &src->chanbase); - - /* remap pointers */ - ghash= BLI_ghash_new(BLI_ghashutil_ptrhash, BLI_ghashutil_ptrcmp); - pchan= src->chanbase.first; - outpchan= out->chanbase.first; - for (; pchan; pchan=pchan->next, outpchan=outpchan->next) - BLI_ghash_insert(ghash, pchan, outpchan); - - for (pchan=out->chanbase.first; pchan; pchan=pchan->next) { - pchan->parent= BLI_ghash_lookup(ghash, pchan->parent); - pchan->child= BLI_ghash_lookup(ghash, pchan->child); - pchan->path= NULL; - } - - BLI_ghash_free(ghash, NULL, NULL); - - *dst=out; -} + /* free IK solver state */ + BIK_clear_data(pose); + /* free IK solver param */ + if (pose->ikparam) + MEM_freeN(pose->ikparam); -/* Only allowed for Poses with identical channels */ -void game_blend_poses(bPose *dst, bPose *src, float srcweight/*, short mode*/) -{ - short mode= ACTSTRIPMODE_BLEND; - - bPoseChannel *dchan; - const bPoseChannel *schan; - bConstraint *dcon, *scon; - float dstweight; - int i; - - switch (mode){ - case ACTSTRIPMODE_BLEND: - dstweight = 1.0F - srcweight; - break; - case ACTSTRIPMODE_ADD: - dstweight = 1.0F; - break; - default : - dstweight = 1.0F; - } - - schan= src->chanbase.first; - for (dchan = dst->chanbase.first; dchan; dchan=dchan->next, schan= schan->next){ - if (schan->flag & (POSE_ROT|POSE_LOC|POSE_SIZE)) { - /* replaced quat->matrix->quat conversion with decent quaternion interpol (ton) */ - - /* Do the transformation blend */ - if (schan->flag & POSE_ROT) { - /* quat interpolation done separate */ - if (schan->rotmode == PCHAN_ROT_QUAT) { - float dquat[4], squat[4]; - - QUATCOPY(dquat, dchan->quat); - QUATCOPY(squat, schan->quat); - if (mode==ACTSTRIPMODE_BLEND) - QuatInterpol(dchan->quat, dquat, squat, srcweight); - else { - QuatMulFac(squat, srcweight); - QuatMul(dchan->quat, dquat, squat); - } - - NormalQuat(dchan->quat); - } - } - - for (i=0; i<3; i++) { - /* blending for loc and scale are pretty self-explanatory... */ - if (schan->flag & POSE_LOC) - dchan->loc[i] = (dchan->loc[i]*dstweight) + (schan->loc[i]*srcweight); - if (schan->flag & POSE_SIZE) - dchan->size[i] = 1.0f + ((dchan->size[i]-1.0f)*dstweight) + ((schan->size[i]-1.0f)*srcweight); - - /* euler-rotation interpolation done here instead... */ - // FIXME: are these results decent? - if ((schan->flag & POSE_ROT) && (schan->rotmode)) - dchan->eul[i] = (dchan->eul[i]*dstweight) + (schan->eul[i]*srcweight); - } - dchan->flag |= schan->flag; - } - for(dcon= dchan->constraints.first, scon= schan->constraints.first; dcon && scon; dcon= dcon->next, scon= scon->next) { - /* no 'add' option for constraint blending */ - dcon->enforce= dcon->enforce*(1.0f-srcweight) + scon->enforce*srcweight; - } - } - - /* this pose is now in src time */ - dst->ctime= src->ctime; -} - -void game_free_pose(bPose *pose) -{ - if (pose) { - /* we don't free constraints, those are owned by the original pose */ - if(pose->chanbase.first) - BLI_freelistN(&pose->chanbase); - + /* free pose */ MEM_freeN(pose); } } @@ -917,7 +847,6 @@ void calc_action_range(const bAction *act, float *start, float *end, short incl_ } } - /* Return flags indicating which transforms the given object/posechannel has * - if 'curves' is provided, a list of links to these curves are also returned */ diff --git a/source/blender/blenkernel/intern/armature.c b/source/blender/blenkernel/intern/armature.c index c880925aa94..b2368451414 100644 --- a/source/blender/blenkernel/intern/armature.c +++ b/source/blender/blenkernel/intern/armature.c @@ -66,10 +66,9 @@ #include "BKE_object.h" #include "BKE_object.h" #include "BKE_utildefines.h" +#include "BIK_api.h" #include "BKE_sketch.h" -#include "IK_solver.h" - #ifdef HAVE_CONFIG_H #include <config.h> #endif @@ -1569,409 +1568,10 @@ void armature_rebuild_pose(Object *ob, bArmature *arm) DAG_pose_sort(ob); ob->pose->flag &= ~POSE_RECALC; + ob->pose->flag |= POSE_WAS_REBUILT; } -/* ********************** THE IK SOLVER ******************* */ - - - -/* allocates PoseTree, and links that to root bone/channel */ -/* Note: detecting the IK chain is duplicate code... in drawarmature.c and in transform_conversions.c */ -static void initialize_posetree(struct Object *ob, bPoseChannel *pchan_tip) -{ - bPoseChannel *curchan, *pchan_root=NULL, *chanlist[256], **oldchan; - PoseTree *tree; - PoseTarget *target; - bConstraint *con; - bKinematicConstraint *data= NULL; - int a, segcount= 0, size, newsize, *oldparent, parent; - - /* find IK constraint, and validate it */ - for(con= pchan_tip->constraints.first; con; con= con->next) { - if(con->type==CONSTRAINT_TYPE_KINEMATIC) { - data=(bKinematicConstraint*)con->data; - if (data->flag & CONSTRAINT_IK_AUTO) break; - if (data->tar==NULL) continue; - if (data->tar->type==OB_ARMATURE && data->subtarget[0]==0) continue; - if ((con->flag & CONSTRAINT_DISABLE)==0 && (con->enforce!=0.0)) break; - } - } - if(con==NULL) return; - - /* exclude tip from chain? */ - if(!(data->flag & CONSTRAINT_IK_TIP)) - pchan_tip= pchan_tip->parent; - - /* Find the chain's root & count the segments needed */ - for (curchan = pchan_tip; curchan; curchan=curchan->parent){ - pchan_root = curchan; - - curchan->flag |= POSE_CHAIN; // don't forget to clear this - chanlist[segcount]=curchan; - segcount++; - - if(segcount==data->rootbone || segcount>255) break; // 255 is weak - } - if (!segcount) return; - - /* setup the chain data */ - - /* we make tree-IK, unless all existing targets are in this chain */ - for(tree= pchan_root->iktree.first; tree; tree= tree->next) { - for(target= tree->targets.first; target; target= target->next) { - curchan= tree->pchan[target->tip]; - if(curchan->flag & POSE_CHAIN) - curchan->flag &= ~POSE_CHAIN; - else - break; - } - if(target) break; - } - - /* create a target */ - target= MEM_callocN(sizeof(PoseTarget), "posetarget"); - target->con= con; - pchan_tip->flag &= ~POSE_CHAIN; - - if(tree==NULL) { - /* make new tree */ - tree= MEM_callocN(sizeof(PoseTree), "posetree"); - - tree->iterations= data->iterations; - tree->totchannel= segcount; - tree->stretch = (data->flag & CONSTRAINT_IK_STRETCH); - - tree->pchan= MEM_callocN(segcount*sizeof(void*), "ik tree pchan"); - tree->parent= MEM_callocN(segcount*sizeof(int), "ik tree parent"); - for(a=0; a<segcount; a++) { - tree->pchan[a]= chanlist[segcount-a-1]; - tree->parent[a]= a-1; - } - target->tip= segcount-1; - - /* AND! link the tree to the root */ - BLI_addtail(&pchan_root->iktree, tree); - } - else { - tree->iterations= MAX2(data->iterations, tree->iterations); - tree->stretch= tree->stretch && !(data->flag & CONSTRAINT_IK_STRETCH); - - /* skip common pose channels and add remaining*/ - size= MIN2(segcount, tree->totchannel); - for(a=0; a<size && tree->pchan[a]==chanlist[segcount-a-1]; a++); - parent= a-1; - - segcount= segcount-a; - target->tip= tree->totchannel + segcount - 1; - - if (segcount > 0) { - /* resize array */ - newsize= tree->totchannel + segcount; - oldchan= tree->pchan; - oldparent= tree->parent; - - tree->pchan= MEM_callocN(newsize*sizeof(void*), "ik tree pchan"); - tree->parent= MEM_callocN(newsize*sizeof(int), "ik tree parent"); - memcpy(tree->pchan, oldchan, sizeof(void*)*tree->totchannel); - memcpy(tree->parent, oldparent, sizeof(int)*tree->totchannel); - MEM_freeN(oldchan); - MEM_freeN(oldparent); - - /* add new pose channels at the end, in reverse order */ - for(a=0; a<segcount; a++) { - tree->pchan[tree->totchannel+a]= chanlist[segcount-a-1]; - tree->parent[tree->totchannel+a]= tree->totchannel+a-1; - } - tree->parent[tree->totchannel]= parent; - - tree->totchannel= newsize; - } - - /* move tree to end of list, for correct evaluation order */ - BLI_remlink(&pchan_root->iktree, tree); - BLI_addtail(&pchan_root->iktree, tree); - } - - /* add target to the tree */ - BLI_addtail(&tree->targets, target); -} - -/* called from within the core where_is_pose loop, all animsystems and constraints -were executed & assigned. Now as last we do an IK pass */ -static void execute_posetree(Object *ob, PoseTree *tree) -{ - float R_parmat[3][3], identity[3][3]; - float iR_parmat[3][3]; - float R_bonemat[3][3]; - float goalrot[3][3], goalpos[3]; - float rootmat[4][4], imat[4][4]; - float goal[4][4], goalinv[4][4]; - float irest_basis[3][3], full_basis[3][3]; - float end_pose[4][4], world_pose[4][4]; - float length, basis[3][3], rest_basis[3][3], start[3], *ikstretch=NULL; - float resultinf=0.0f; - int a, flag, hasstretch=0, resultblend=0; - bPoseChannel *pchan; - IK_Segment *seg, *parent, **iktree, *iktarget; - IK_Solver *solver; - PoseTarget *target; - bKinematicConstraint *data, *poleangledata=NULL; - Bone *bone; - - if (tree->totchannel == 0) - return; - - iktree= MEM_mallocN(sizeof(void*)*tree->totchannel, "ik tree"); - - for(a=0; a<tree->totchannel; a++) { - pchan= tree->pchan[a]; - bone= pchan->bone; - - /* set DoF flag */ - flag= 0; - if(!(pchan->ikflag & BONE_IK_NO_XDOF) && !(pchan->ikflag & BONE_IK_NO_XDOF_TEMP)) - flag |= IK_XDOF; - if(!(pchan->ikflag & BONE_IK_NO_YDOF) && !(pchan->ikflag & BONE_IK_NO_YDOF_TEMP)) - flag |= IK_YDOF; - if(!(pchan->ikflag & BONE_IK_NO_ZDOF) && !(pchan->ikflag & BONE_IK_NO_ZDOF_TEMP)) - flag |= IK_ZDOF; - - if(tree->stretch && (pchan->ikstretch > 0.0)) { - flag |= IK_TRANS_YDOF; - hasstretch = 1; - } - - seg= iktree[a]= IK_CreateSegment(flag); - - /* find parent */ - if(a == 0) - parent= NULL; - else - parent= iktree[tree->parent[a]]; - - IK_SetParent(seg, parent); - - /* get the matrix that transforms from prevbone into this bone */ - Mat3CpyMat4(R_bonemat, pchan->pose_mat); - - /* gather transformations for this IK segment */ - - if (pchan->parent) - Mat3CpyMat4(R_parmat, pchan->parent->pose_mat); - else - Mat3One(R_parmat); - - /* bone offset */ - if (pchan->parent && (a > 0)) - VecSubf(start, pchan->pose_head, pchan->parent->pose_tail); - else - /* only root bone (a = 0) has no parent */ - start[0]= start[1]= start[2]= 0.0f; - - /* change length based on bone size */ - length= bone->length*VecLength(R_bonemat[1]); - - /* compute rest basis and its inverse */ - Mat3CpyMat3(rest_basis, bone->bone_mat); - Mat3CpyMat3(irest_basis, bone->bone_mat); - Mat3Transp(irest_basis); - - /* compute basis with rest_basis removed */ - Mat3Inv(iR_parmat, R_parmat); - Mat3MulMat3(full_basis, iR_parmat, R_bonemat); - Mat3MulMat3(basis, irest_basis, full_basis); - - /* basis must be pure rotation */ - Mat3Ortho(basis); - - /* transform offset into local bone space */ - Mat3Ortho(iR_parmat); - Mat3MulVecfl(iR_parmat, start); - - IK_SetTransform(seg, start, rest_basis, basis, length); - - if (pchan->ikflag & BONE_IK_XLIMIT) - IK_SetLimit(seg, IK_X, pchan->limitmin[0], pchan->limitmax[0]); - if (pchan->ikflag & BONE_IK_YLIMIT) - IK_SetLimit(seg, IK_Y, pchan->limitmin[1], pchan->limitmax[1]); - if (pchan->ikflag & BONE_IK_ZLIMIT) - IK_SetLimit(seg, IK_Z, pchan->limitmin[2], pchan->limitmax[2]); - - IK_SetStiffness(seg, IK_X, pchan->stiffness[0]); - IK_SetStiffness(seg, IK_Y, pchan->stiffness[1]); - IK_SetStiffness(seg, IK_Z, pchan->stiffness[2]); - - if(tree->stretch && (pchan->ikstretch > 0.0f)) { - float ikstretch = pchan->ikstretch*pchan->ikstretch; - IK_SetStiffness(seg, IK_TRANS_Y, MIN2(1.0f-ikstretch, 0.99f)); - IK_SetLimit(seg, IK_TRANS_Y, 0.001f, 1e10); - } - } - - solver= IK_CreateSolver(iktree[0]); - - /* set solver goals */ - - /* first set the goal inverse transform, assuming the root of tree was done ok! */ - pchan= tree->pchan[0]; - if (pchan->parent) - /* transform goal by parent mat, so this rotation is not part of the - segment's basis. otherwise rotation limits do not work on the - local transform of the segment itself. */ - Mat4CpyMat4(rootmat, pchan->parent->pose_mat); - else - Mat4One(rootmat); - VECCOPY(rootmat[3], pchan->pose_head); - - Mat4MulMat4 (imat, rootmat, ob->obmat); - 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, 0, CONSTRAINT_OBTYPE_OBJECT, ob, rootmat, 1.0); - - /* and set and transform goal */ - Mat4MulMat4(goal, rootmat, goalinv); - - 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; - - /* for pole targets, we blend the result of the ik solver - * instead of the target position, otherwise we can't get - * a smooth transition */ - resultblend= 1; - resultinf= target->con->enforce; - - if(data->flag & CONSTRAINT_IK_GETANGLE) { - poleangledata= data; - data->flag &= ~CONSTRAINT_IK_GETANGLE; - } - } - } - - /* do we need blending? */ - if (!resultblend && target->con->enforce!=1.0f) { - float q1[4], q2[4], q[4]; - float fac= target->con->enforce; - float mfac= 1.0f-fac; - - pchan= tree->pchan[target->tip]; - - /* end effector in world space */ - Mat4CpyMat4(end_pose, pchan->pose_mat); - VECCOPY(end_pose[3], pchan->pose_tail); - Mat4MulSerie(world_pose, goalinv, ob->obmat, end_pose, 0, 0, 0, 0, 0); - - /* blend position */ - goalpos[0]= fac*goalpos[0] + mfac*world_pose[3][0]; - goalpos[1]= fac*goalpos[1] + mfac*world_pose[3][1]; - goalpos[2]= fac*goalpos[2] + mfac*world_pose[3][2]; - - /* blend rotation */ - Mat3ToQuat(goalrot, q1); - Mat4ToQuat(world_pose, q2); - QuatInterpol(q, q1, q2, mfac); - QuatToMat3(q, goalrot); - } - - iktarget= iktree[target->tip]; - - if(data->weight != 0.0f) { - if(poleconstrain) - IK_SolverSetPoleVectorConstraint(solver, iktarget, goalpos, - polepos, data->poleangle*(float)M_PI/180.0f, (poleangledata == data)); - IK_SolverAddGoal(solver, iktarget, goalpos, data->weight); - } - if((data->flag & CONSTRAINT_IK_ROT) && (data->orientweight != 0.0f)) - 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.0f/(float)M_PI; - - IK_FreeSolver(solver); - - /* gather basis changes */ - tree->basis_change= MEM_mallocN(sizeof(float[3][3])*tree->totchannel, "ik basis change"); - if(hasstretch) - ikstretch= MEM_mallocN(sizeof(float)*tree->totchannel, "ik stretch"); - - for(a=0; a<tree->totchannel; a++) { - IK_GetBasisChange(iktree[a], tree->basis_change[a]); - - if(hasstretch) { - /* have to compensate for scaling received from parent */ - float parentstretch, stretch; - - pchan= tree->pchan[a]; - parentstretch= (tree->parent[a] >= 0)? ikstretch[tree->parent[a]]: 1.0f; - - if(tree->stretch && (pchan->ikstretch > 0.0f)) { - float trans[3], length; - - IK_GetTranslationChange(iktree[a], trans); - length= pchan->bone->length*VecLength(pchan->pose_mat[1]); - - ikstretch[a]= (length == 0.0f)? 1.0f: (trans[1]+length)/length; - } - else - ikstretch[a] = 1.0f; - - stretch= (parentstretch == 0.0f)? 1.0f: ikstretch[a]/parentstretch; - - VecMulf(tree->basis_change[a][0], stretch); - VecMulf(tree->basis_change[a][1], stretch); - VecMulf(tree->basis_change[a][2], stretch); - } - - if(resultblend && resultinf!=1.0f) { - Mat3One(identity); - Mat3BlendMat3(tree->basis_change[a], identity, - tree->basis_change[a], resultinf); - } - - IK_FreeSegment(iktree[a]); - } - - MEM_freeN(iktree); - if(ikstretch) MEM_freeN(ikstretch); -} - -void free_posetree(PoseTree *tree) -{ - BLI_freelistN(&tree->targets); - if(tree->pchan) MEM_freeN(tree->pchan); - if(tree->parent) MEM_freeN(tree->parent); - if(tree->basis_change) MEM_freeN(tree->basis_change); - MEM_freeN(tree); -} - /* ********************** THE POSE SOLVER ******************* */ @@ -2012,41 +1612,6 @@ void chan_calc_mat(bPoseChannel *chan) } } -/* transform from bone(b) to bone(b+1), store in chan_mat */ -static void make_dmats(bPoseChannel *pchan) -{ - if (pchan->parent) { - float iR_parmat[4][4]; - Mat4Invert(iR_parmat, pchan->parent->pose_mat); - Mat4MulMat4(pchan->chan_mat, pchan->pose_mat, iR_parmat); // delta mat - } - else Mat4CpyMat4(pchan->chan_mat, pchan->pose_mat); -} - -/* applies IK matrix to pchan, IK is done separated */ -/* formula: pose_mat(b) = pose_mat(b-1) * diffmat(b-1, b) * ik_mat(b) */ -/* to make this work, the diffmats have to be precalculated! Stored in chan_mat */ -static void where_is_ik_bone(bPoseChannel *pchan, float ik_mat[][3]) // nr = to detect if this is first bone -{ - float vec[3], ikmat[4][4]; - - Mat4CpyMat3(ikmat, ik_mat); - - if (pchan->parent) - Mat4MulSerie(pchan->pose_mat, pchan->parent->pose_mat, pchan->chan_mat, ikmat, NULL, NULL, NULL, NULL, NULL); - else - Mat4MulMat4(pchan->pose_mat, ikmat, pchan->chan_mat); - - /* calculate head */ - VECCOPY(pchan->pose_head, pchan->pose_mat[3]); - /* calculate tail */ - VECCOPY(vec, pchan->pose_mat[1]); - VecMulf(vec, pchan->bone->length); - VecAddf(pchan->pose_tail, pchan->pose_head, vec); - - pchan->flag |= POSE_DONE; -} - /* NLA strip modifiers */ static void do_strip_modifiers(Scene *scene, Object *armob, Bone *bone, bPoseChannel *pchan) { @@ -2172,7 +1737,7 @@ static void do_strip_modifiers(Scene *scene, Object *armob, Bone *bone, bPoseCha /* The main armature solver, does all constraints excluding IK */ /* pchan is validated, as having bone and parent pointer */ -static void where_is_pose_bone(Scene *scene, Object *ob, bPoseChannel *pchan, float ctime) +void where_is_pose_bone(Scene *scene, Object *ob, bPoseChannel *pchan, float ctime) { Bone *bone, *parbone; bPoseChannel *parchan; @@ -2312,48 +1877,27 @@ void where_is_pose (Scene *scene, Object *ob) else { Mat4Invert(ob->imat, ob->obmat); // imat is needed - /* 1. construct the PoseTrees, clear flags */ + /* 1. clear flags */ for(pchan= ob->pose->chanbase.first; pchan; pchan= pchan->next) { - pchan->flag &= ~(POSE_DONE|POSE_CHAIN); - if(pchan->constflag & PCHAN_HAS_IK) // flag is set on editing constraints - initialize_posetree(ob, pchan); // will attach it to root! + pchan->flag &= ~(POSE_DONE|POSE_CHAIN|POSE_IKTREE); } - - /* 2. the main loop, channels are already hierarchical sorted from root to children */ + /* 2. construct the IK tree */ + BIK_initialize_tree(scene, ob, ctime); + + /* 3. the main loop, channels are already hierarchical sorted from root to children */ for(pchan= ob->pose->chanbase.first; pchan; pchan= pchan->next) { - /* 3. if we find an IK root, we handle it separated */ - if(pchan->iktree.first) { - while(pchan->iktree.first) { - PoseTree *tree= pchan->iktree.first; - int a; - - /* 4. walk over the tree for regular solving */ - for(a=0; a<tree->totchannel; a++) { - if(!(tree->pchan[a]->flag & POSE_DONE)) // successive trees can set the flag - where_is_pose_bone(scene, ob, tree->pchan[a], ctime); - } - /* 5. execute the IK solver */ - execute_posetree(ob, tree); - - /* 6. apply the differences to the channels, - we need to calculate the original differences first */ - for(a=0; a<tree->totchannel; a++) - make_dmats(tree->pchan[a]); - - for(a=0; a<tree->totchannel; a++) - /* sets POSE_DONE */ - where_is_ik_bone(tree->pchan[a], tree->basis_change[a]); - - /* 7. and free */ - BLI_remlink(&pchan->iktree, tree); - free_posetree(tree); - } + /* 4. if we find an IK root, we handle it separated */ + if(pchan->flag & POSE_IKTREE) { + BIK_execute_tree(scene, ob, pchan, ctime); } + /* 5. otherwise just call the normal solver */ else if(!(pchan->flag & POSE_DONE)) { where_is_pose_bone(scene, ob, pchan, ctime); } } + /* 6. release the IK tree */ + BIK_release_tree(scene, ob, ctime); } /* calculating deform matrices */ diff --git a/source/blender/blenkernel/intern/constraint.c b/source/blender/blenkernel/intern/constraint.c index a3d59720645..b8d6b333674 100644 --- a/source/blender/blenkernel/intern/constraint.c +++ b/source/blender/blenkernel/intern/constraint.c @@ -1053,6 +1053,7 @@ static void kinematic_new_data (void *cdata) data->weight= (float)1.0; data->orientweight= (float)1.0; data->iterations = 500; + data->dist= (float)1.0; data->flag= CONSTRAINT_IK_TIP|CONSTRAINT_IK_STRETCH|CONSTRAINT_IK_POS; } @@ -3643,7 +3644,7 @@ void solve_constraints (ListBase *conlist, bConstraintOb *cob, float ctime) /* these we can skip completely (invalid constraints...) */ if (cti == NULL) continue; - if (con->flag & CONSTRAINT_DISABLE) continue; + if (con->flag & (CONSTRAINT_DISABLE|CONSTRAINT_OFF)) continue; /* these constraints can't be evaluated anyway */ if (cti->evaluate_constraint == NULL) continue; /* influence == 0 should be ignored */ diff --git a/source/blender/blenkernel/intern/pointcache.c b/source/blender/blenkernel/intern/pointcache.c index dfc5b4cd770..e5f89727ab8 100644 --- a/source/blender/blenkernel/intern/pointcache.c +++ b/source/blender/blenkernel/intern/pointcache.c @@ -56,6 +56,7 @@ #include "BKE_smoke.h" #include "BKE_softbody.h" #include "BKE_utildefines.h" +#include "BIK_api.h" #include "BLI_blenlib.h" @@ -2007,6 +2008,9 @@ int BKE_ptcache_object_reset(Scene *scene, Object *ob, int mode) } } + if (ob->type == OB_ARMATURE) + BIK_clear_cache(ob->pose); + return reset; } diff --git a/source/blender/blenkernel/intern/sca.c b/source/blender/blenkernel/intern/sca.c index de2118af202..5cd554725ff 100644 --- a/source/blender/blenkernel/intern/sca.c +++ b/source/blender/blenkernel/intern/sca.c @@ -128,6 +128,9 @@ void init_sensor(bSensor *sens) case SENS_PROPERTY: sens->data= MEM_callocN(sizeof(bPropertySensor), "propsens"); break; + case SENS_ARMATURE: + sens->data= MEM_callocN(sizeof(bArmatureSensor), "armsens"); + break; case SENS_ACTUATOR: sens->data= MEM_callocN(sizeof(bActuatorSensor), "actsens"); break; @@ -455,6 +458,9 @@ void init_actuator(bActuator *act) case ACT_STATE: act->data = MEM_callocN(sizeof( bStateActuator ), "state act"); break; + case ACT_ARMATURE: + act->data = MEM_callocN(sizeof( bArmatureActuator ), "armature act"); + break; default: ; /* this is very severe... I cannot make any memory for this */ /* logic brick... */ @@ -596,6 +602,8 @@ void sca_remove_ob_poin(Object *obt, Object *ob) bEditObjectActuator *eoa; bPropertyActuator *pa; bMessageActuator *ma; + bParentActuator *para; + bArmatureActuator *aa; sens= obt->sensors.first; while(sens) { @@ -634,7 +642,15 @@ void sca_remove_ob_poin(Object *obt, Object *ob) ma= act->data; if(ma->toObject==ob) ma->toObject= NULL; break; - + case ACT_PARENT: + para = act->data; + if (para->ob==ob) para->ob = NULL; + break; + case ACT_ARMATURE: + aa = act->data; + if (aa->target == ob) aa->target = NULL; + if (aa->subtarget == ob) aa->subtarget = NULL; + break; } act= act->next; } |