Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'source/blender/blenkernel')
-rw-r--r--source/blender/blenkernel/BKE_action.h23
-rw-r--r--source/blender/blenkernel/BKE_armature.h6
-rw-r--r--source/blender/blenkernel/BKE_constraint.h6
-rw-r--r--source/blender/blenkernel/CMakeLists.txt2
-rw-r--r--source/blender/blenkernel/SConscript2
-rw-r--r--source/blender/blenkernel/intern/Makefile1
-rw-r--r--source/blender/blenkernel/intern/action.c185
-rw-r--r--source/blender/blenkernel/intern/armature.c486
-rw-r--r--source/blender/blenkernel/intern/constraint.c3
-rw-r--r--source/blender/blenkernel/intern/pointcache.c4
-rw-r--r--source/blender/blenkernel/intern/sca.c18
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;
}