diff options
author | Dalai Felinto <dfelinto@gmail.com> | 2015-09-24 18:24:20 +0300 |
---|---|---|
committer | Dalai Felinto <dfelinto@gmail.com> | 2015-09-24 18:24:20 +0300 |
commit | 27b3ea622f8bd313a8e2827dfec752bf2125566c (patch) | |
tree | f212e49d224ce8e1cfc3b17a64ae524711494391 /source/blender/blenkernel/intern/armature.c | |
parent | 372dff8d1dc7e24d4b2cd37de245588ecfce8bfa (diff) | |
parent | de80e687689032cb85179a1f7e89750573631d5d (diff) |
Merge remote-tracking branch 'origin/master' into cycles_camera_nodescycles_camera_nodes
Note: the branch currently crashes in blender_camera_nodes.cpp:
BL::NodeTree b_ntree = b_data.node_groups[nodes_tree_name];
The crash was introduced in:
cb7cf523e5c000609f32a382e2c0fcc57f635a42
Conflicts:
intern/cycles/SConscript
intern/cycles/blender/addon/__init__.py
intern/cycles/blender/addon/properties.py
intern/cycles/blender/blender_camera.cpp
intern/cycles/kernel/kernel_types.h
intern/cycles/kernel/svm/svm.h
intern/cycles/kernel/svm/svm_types.h
intern/cycles/render/camera.cpp
intern/cycles/render/camera.h
Diffstat (limited to 'source/blender/blenkernel/intern/armature.c')
-rw-r--r-- | source/blender/blenkernel/intern/armature.c | 599 |
1 files changed, 128 insertions, 471 deletions
diff --git a/source/blender/blenkernel/intern/armature.c b/source/blender/blenkernel/intern/armature.c index bb05b5de8a6..6afe7f1abe9 100644 --- a/source/blender/blenkernel/intern/armature.c +++ b/source/blender/blenkernel/intern/armature.c @@ -127,7 +127,7 @@ void BKE_armature_free(bArmature *arm) /* free animation data */ if (arm->adt) { - BKE_free_animdata(&arm->id); + BKE_animdata_free(&arm->id); arm->adt = NULL; } } @@ -222,6 +222,10 @@ bArmature *BKE_armature_copy(bArmature *arm) newArm->act_edbone = NULL; newArm->sketch = NULL; + if (arm->id.lib) { + BKE_id_lib_local_paths(G.main, arm->id.lib, &newArm->id); + } + return newArm; } @@ -229,7 +233,7 @@ static Bone *get_named_bone_bonechildren(Bone *bone, const char *name) { Bone *curBone, *rbone; - if (!strcmp(bone->name, name)) + if (STREQ(bone->name, name)) return bone; for (curBone = bone->childbase.first; curBone; curBone = curBone->next) { @@ -259,6 +263,19 @@ Bone *BKE_armature_find_bone_name(bArmature *arm, const char *name) return bone; } +bool BKE_armature_bone_flag_test_recursive(const Bone *bone, int flag) +{ + if (bone->flag & flag) { + return true; + } + else if (bone->parent) { + return BKE_armature_bone_flag_test_recursive(bone->parent, flag); + } + else { + return false; + } +} + /* Finds the best possible extension to the name on a particular axis. (For renaming, check for * unique names afterwards) strip_number: removes number extensions (TODO: not used) * axis: the axis to name on @@ -840,7 +857,7 @@ void armature_deform_verts(Object *armOb, Object *target, DerivedMesh *dm, float /* bone defmats are already in the channels, chan_mat */ /* initialize B_bone matrices and dual quaternions */ - totchan = BLI_countlist(&armOb->pose->chanbase); + totchan = BLI_listbase_count(&armOb->pose->chanbase); if (use_quaternion) { dualquats = MEM_callocN(sizeof(DualQuat) * totchan, "dualquats"); @@ -866,7 +883,7 @@ void armature_deform_verts(Object *armOb, Object *target, DerivedMesh *dm, float armature_def_nr = defgroup_name_index(target, defgrp_name); if (ELEM(target->type, OB_MESH, OB_LATTICE)) { - defbase_tot = BLI_countlist(&target->defbase); + defbase_tot = BLI_listbase_count(&target->defbase); if (target->type == OB_MESH) { Mesh *me = target->data; @@ -1124,8 +1141,7 @@ void BKE_armature_loc_world_to_pose(Object *ob, const float inloc[3], float outl * Not exported, as it is only used in this file currently... */ static void get_offset_bone_mat(Bone *bone, float offs_bone[4][4]) { - if (!bone->parent) - return; + BLI_assert(bone->parent != NULL); /* Bone transform itself. */ copy_m4_m3(offs_bone, bone->bone_mat); @@ -1489,6 +1505,8 @@ void vec_roll_to_mat3_normalized(const float nor[3], const float roll, float mat float theta; float rMatrix[3][3], bMatrix[3][3]; + BLI_ASSERT_UNIT_V3(nor); + theta = 1.0f + nor[1]; /* With old algo, 1.0e-13f caused T23954 and T31333, 1.0e-6f caused T27675 and T30438, @@ -1549,16 +1567,15 @@ void vec_roll_to_mat3(const float vec[3], const float roll, float mat[3][3]) /* recursive part, calculates restposition of entire tree of children */ /* used by exiting editmode too */ -void BKE_armature_where_is_bone(Bone *bone, Bone *prevbone) +void BKE_armature_where_is_bone(Bone *bone, Bone *prevbone, const bool use_recursion) { float vec[3]; /* Bone Space */ sub_v3_v3v3(vec, bone->tail, bone->head); + bone->length = len_v3(vec); vec_roll_to_mat3(vec, bone->roll, bone->bone_mat); - bone->length = len_v3v3(bone->head, bone->tail); - /* this is called on old file reading too... */ if (bone->xwidth == 0.0f) { bone->xwidth = 0.1f; @@ -1580,9 +1597,11 @@ void BKE_armature_where_is_bone(Bone *bone, Bone *prevbone) } /* and the kiddies */ - prevbone = bone; - for (bone = bone->childbase.first; bone; bone = bone->next) { - BKE_armature_where_is_bone(bone, prevbone); + if (use_recursion) { + prevbone = bone; + for (bone = bone->childbase.first; bone; bone = bone->next) { + BKE_armature_where_is_bone(bone, prevbone, use_recursion); + } } } @@ -1594,7 +1613,7 @@ void BKE_armature_where_is(bArmature *arm) /* hierarchical from root to children */ for (bone = arm->bonebase.first; bone; bone = bone->next) { - BKE_armature_where_is_bone(bone, NULL); + BKE_armature_where_is_bone(bone, NULL, true); } } @@ -1654,6 +1673,7 @@ static void pose_proxy_synchronize(Object *ob, Object *from, int layer_protected pchanw.next = pchan->next; pchanw.parent = pchan->parent; pchanw.child = pchan->child; + pchanw.custom_tx = pchan->custom_tx; pchanw.mpath = pchan->mpath; pchan->mpath = NULL; @@ -1662,7 +1682,7 @@ static void pose_proxy_synchronize(Object *ob, Object *from, int layer_protected if (pchanw.prop) { pchanw.prop = IDP_CopyProperty(pchanw.prop); - /* use the values from the the existing props */ + /* use the values from the existing props */ if (pchan->prop) { IDP_SyncGroupValues(pchanw.prop, pchan->prop); } @@ -1682,7 +1702,7 @@ static void pose_proxy_synchronize(Object *ob, Object *from, int layer_protected /* constraints - set target ob pointer to own object */ for (con = pchanw.constraints.first; con; con = con->next) { - bConstraintTypeInfo *cti = BKE_constraint_typeinfo_get(con); + const bConstraintTypeInfo *cti = BKE_constraint_typeinfo_get(con); ListBase targets = {NULL, NULL}; bConstraintTarget *ct; @@ -1807,9 +1827,12 @@ void BKE_pose_rebuild(Object *ob, bArmature *arm) BKE_pose_update_constraint_flags(ob->pose); /* for IK detection for example */ +#ifdef WITH_LEGACY_DEPSGRAPH /* the sorting */ + /* Sorting for new dependnecy graph is done on the scene graph level. */ if (counter > 1) DAG_pose_sort(ob); +#endif ob->pose->flag &= ~POSE_RECALC; ob->pose->flag |= POSE_WAS_REBUILT; @@ -1817,443 +1840,6 @@ void BKE_pose_rebuild(Object *ob, bArmature *arm) BKE_pose_channels_hash_make(ob->pose); } - -/* ********************** SPLINE IK SOLVER ******************* */ - -/* Temporary evaluation tree data used for Spline IK */ -typedef struct tSplineIK_Tree { - struct tSplineIK_Tree *next, *prev; - - int type; /* type of IK that this serves (CONSTRAINT_TYPE_KINEMATIC or ..._SPLINEIK) */ - - bool free_points; /* free the point positions array */ - short chainlen; /* number of bones in the chain */ - - float *points; /* parametric positions for the joints along the curve */ - bPoseChannel **chain; /* chain of bones to affect using Spline IK (ordered from the tip) */ - - bPoseChannel *root; /* bone that is the root node of the chain */ - - bConstraint *con; /* constraint for this chain */ - bSplineIKConstraint *ikData; /* constraint settings for this chain */ -} tSplineIK_Tree; - -/* ----------- */ - -/* Tag the bones in the chain formed by the given bone for IK */ -static void splineik_init_tree_from_pchan(Scene *scene, Object *UNUSED(ob), bPoseChannel *pchan_tip) -{ - bPoseChannel *pchan, *pchanRoot = NULL; - bPoseChannel *pchanChain[255]; - bConstraint *con = NULL; - bSplineIKConstraint *ikData = NULL; - float boneLengths[255], *jointPoints; - float totLength = 0.0f; - bool free_joints = 0; - int segcount = 0; - - /* find the SplineIK constraint */ - for (con = pchan_tip->constraints.first; con; con = con->next) { - if (con->type == CONSTRAINT_TYPE_SPLINEIK) { - ikData = con->data; - - /* target can only be curve */ - if ((ikData->tar == NULL) || (ikData->tar->type != OB_CURVE)) - continue; - /* skip if disabled */ - if ((con->enforce == 0.0f) || (con->flag & (CONSTRAINT_DISABLE | CONSTRAINT_OFF))) - continue; - - /* otherwise, constraint is ok... */ - break; - } - } - if (con == NULL) - return; - - /* make sure that the constraint targets are ok - * - this is a workaround for a depsgraph bug... - */ - if (ikData->tar) { - /* note: when creating constraints that follow path, the curve gets the CU_PATH set now, - * currently for paths to work it needs to go through the bevlist/displist system (ton) - */ - - /* only happens on reload file, but violates depsgraph still... fix! */ - if (ELEM(NULL, ikData->tar->curve_cache, ikData->tar->curve_cache->path, ikData->tar->curve_cache->path->data)) { - BKE_displist_make_curveTypes(scene, ikData->tar, 0); - - /* path building may fail in EditMode after removing verts [#33268]*/ - if (ELEM(NULL, ikData->tar->curve_cache->path, ikData->tar->curve_cache->path->data)) { - /* BLI_assert(cu->path != NULL); */ - return; - } - } - } - - /* find the root bone and the chain of bones from the root to the tip - * NOTE: this assumes that the bones are connected, but that may not be true... */ - for (pchan = pchan_tip; pchan && (segcount < ikData->chainlen); pchan = pchan->parent, segcount++) { - /* store this segment in the chain */ - pchanChain[segcount] = pchan; - - /* if performing rebinding, calculate the length of the bone */ - boneLengths[segcount] = pchan->bone->length; - totLength += boneLengths[segcount]; - } - - if (segcount == 0) - return; - else - pchanRoot = pchanChain[segcount - 1]; - - /* perform binding step if required */ - if ((ikData->flag & CONSTRAINT_SPLINEIK_BOUND) == 0) { - float segmentLen = (1.0f / (float)segcount); - int i; - - /* setup new empty array for the points list */ - if (ikData->points) - MEM_freeN(ikData->points); - ikData->numpoints = ikData->chainlen + 1; - ikData->points = MEM_callocN(sizeof(float) * ikData->numpoints, "Spline IK Binding"); - - /* bind 'tip' of chain (i.e. first joint = tip of bone with the Spline IK Constraint) */ - ikData->points[0] = 1.0f; - - /* perform binding of the joints to parametric positions along the curve based - * proportion of the total length that each bone occupies - */ - for (i = 0; i < segcount; i++) { - /* 'head' joints, traveling towards the root of the chain - * - 2 methods; the one chosen depends on whether we've got usable lengths - */ - if ((ikData->flag & CONSTRAINT_SPLINEIK_EVENSPLITS) || (totLength == 0.0f)) { - /* 1) equi-spaced joints */ - ikData->points[i + 1] = ikData->points[i] - segmentLen; - } - else { - /* 2) to find this point on the curve, we take a step from the previous joint - * a distance given by the proportion that this bone takes - */ - ikData->points[i + 1] = ikData->points[i] - (boneLengths[i] / totLength); - } - } - - /* spline has now been bound */ - ikData->flag |= CONSTRAINT_SPLINEIK_BOUND; - } - - /* apply corrections for sensitivity to scaling on a copy of the bind points, - * since it's easier to determine the positions of all the joints beforehand this way - */ - if ((ikData->flag & CONSTRAINT_SPLINEIK_SCALE_LIMITED) && (totLength != 0.0f)) { - float splineLen, maxScale; - int i; - - /* make a copy of the points array, that we'll store in the tree - * - although we could just multiply the points on the fly, this approach means that - * we can introduce per-segment stretchiness later if it is necessary - */ - jointPoints = MEM_dupallocN(ikData->points); - free_joints = 1; - - /* get the current length of the curve */ - /* NOTE: this is assumed to be correct even after the curve was resized */ - splineLen = ikData->tar->curve_cache->path->totdist; - - /* calculate the scale factor to multiply all the path values by so that the - * bone chain retains its current length, such that - * maxScale * splineLen = totLength - */ - maxScale = totLength / splineLen; - - /* apply scaling correction to all of the temporary points */ - /* TODO: this is really not adequate enough on really short chains */ - for (i = 0; i < segcount; i++) - jointPoints[i] *= maxScale; - } - else { - /* just use the existing points array */ - jointPoints = ikData->points; - free_joints = 0; - } - - /* make a new Spline-IK chain, and store it in the IK chains */ - /* TODO: we should check if there is already an IK chain on this, since that would take presidence... */ - { - /* make new tree */ - tSplineIK_Tree *tree = MEM_callocN(sizeof(tSplineIK_Tree), "SplineIK Tree"); - tree->type = CONSTRAINT_TYPE_SPLINEIK; - - tree->chainlen = segcount; - - /* copy over the array of links to bones in the chain (from tip to root) */ - tree->chain = MEM_callocN(sizeof(bPoseChannel *) * segcount, "SplineIK Chain"); - memcpy(tree->chain, pchanChain, sizeof(bPoseChannel *) * segcount); - - /* store reference to joint position array */ - tree->points = jointPoints; - tree->free_points = free_joints; - - /* store references to different parts of the chain */ - tree->root = pchanRoot; - tree->con = con; - tree->ikData = ikData; - - /* AND! link the tree to the root */ - BLI_addtail(&pchanRoot->siktree, tree); - } - - /* mark root channel having an IK tree */ - pchanRoot->flag |= POSE_IKSPLINE; -} - -/* Tag which bones are members of Spline IK chains */ -static void splineik_init_tree(Scene *scene, Object *ob, float UNUSED(ctime)) -{ - bPoseChannel *pchan; - - /* find the tips of Spline IK chains, which are simply the bones which have been tagged as such */ - for (pchan = ob->pose->chanbase.first; pchan; pchan = pchan->next) { - if (pchan->constflag & PCHAN_HAS_SPLINEIK) - splineik_init_tree_from_pchan(scene, ob, pchan); - } -} - -/* ----------- */ - -/* Evaluate spline IK for a given bone */ -static void splineik_evaluate_bone(tSplineIK_Tree *tree, Scene *scene, Object *ob, bPoseChannel *pchan, - int index, float ctime) -{ - bSplineIKConstraint *ikData = tree->ikData; - float poseHead[3], poseTail[3], poseMat[4][4]; - float splineVec[3], scaleFac, radius = 1.0f; - - /* firstly, calculate the bone matrix the standard way, since this is needed for roll control */ - BKE_pose_where_is_bone(scene, ob, pchan, ctime, 1); - - copy_v3_v3(poseHead, pchan->pose_head); - copy_v3_v3(poseTail, pchan->pose_tail); - - /* step 1: determine the positions for the endpoints of the bone */ - { - float vec[4], dir[3], rad; - float tailBlendFac = 1.0f; - - /* determine if the bone should still be affected by SplineIK */ - if (tree->points[index + 1] >= 1.0f) { - /* spline doesn't affect the bone anymore, so done... */ - pchan->flag |= POSE_DONE; - return; - } - else if ((tree->points[index] >= 1.0f) && (tree->points[index + 1] < 1.0f)) { - /* blending factor depends on the amount of the bone still left on the chain */ - tailBlendFac = (1.0f - tree->points[index + 1]) / (tree->points[index] - tree->points[index + 1]); - } - - /* tail endpoint */ - if (where_on_path(ikData->tar, tree->points[index], vec, dir, NULL, &rad, NULL)) { - /* apply curve's object-mode transforms to the position - * unless the option to allow curve to be positioned elsewhere is activated (i.e. no root) - */ - if ((ikData->flag & CONSTRAINT_SPLINEIK_NO_ROOT) == 0) - mul_m4_v3(ikData->tar->obmat, vec); - - /* convert the position to pose-space, then store it */ - mul_m4_v3(ob->imat, vec); - interp_v3_v3v3(poseTail, pchan->pose_tail, vec, tailBlendFac); - - /* set the new radius */ - radius = rad; - } - - /* head endpoint */ - if (where_on_path(ikData->tar, tree->points[index + 1], vec, dir, NULL, &rad, NULL)) { - /* apply curve's object-mode transforms to the position - * unless the option to allow curve to be positioned elsewhere is activated (i.e. no root) - */ - if ((ikData->flag & CONSTRAINT_SPLINEIK_NO_ROOT) == 0) - mul_m4_v3(ikData->tar->obmat, vec); - - /* store the position, and convert it to pose space */ - mul_m4_v3(ob->imat, vec); - copy_v3_v3(poseHead, vec); - - /* set the new radius (it should be the average value) */ - radius = (radius + rad) / 2; - } - } - - /* step 2: determine the implied transform from these endpoints - * - splineVec: the vector direction that the spline applies on the bone - * - scaleFac: the factor that the bone length is scaled by to get the desired amount - */ - sub_v3_v3v3(splineVec, poseTail, poseHead); - scaleFac = len_v3(splineVec) / pchan->bone->length; - - /* step 3: compute the shortest rotation needed to map from the bone rotation to the current axis - * - this uses the same method as is used for the Damped Track Constraint (see the code there for details) - */ - { - float dmat[3][3], rmat[3][3], tmat[3][3]; - float raxis[3], rangle; - - /* compute the raw rotation matrix from the bone's current matrix by extracting only the - * orientation-relevant axes, and normalizing them - */ - copy_v3_v3(rmat[0], pchan->pose_mat[0]); - copy_v3_v3(rmat[1], pchan->pose_mat[1]); - copy_v3_v3(rmat[2], pchan->pose_mat[2]); - normalize_m3(rmat); - - /* also, normalize the orientation imposed by the bone, now that we've extracted the scale factor */ - normalize_v3(splineVec); - - /* calculate smallest axis-angle rotation necessary for getting from the - * current orientation of the bone, to the spline-imposed direction - */ - cross_v3_v3v3(raxis, rmat[1], splineVec); - - rangle = dot_v3v3(rmat[1], splineVec); - CLAMP(rangle, -1.0f, 1.0f); - rangle = acosf(rangle); - - /* multiply the magnitude of the angle by the influence of the constraint to - * control the influence of the SplineIK effect - */ - rangle *= tree->con->enforce; - - /* construct rotation matrix from the axis-angle rotation found above - * - this call takes care to make sure that the axis provided is a unit vector first - */ - axis_angle_to_mat3(dmat, raxis, rangle); - - /* combine these rotations so that the y-axis of the bone is now aligned as the spline dictates, - * while still maintaining roll control from the existing bone animation - */ - mul_m3_m3m3(tmat, dmat, rmat); /* m1, m3, m2 */ - normalize_m3(tmat); /* attempt to reduce shearing, though I doubt this'll really help too much now... */ - copy_m4_m3(poseMat, tmat); - } - - /* step 4: set the scaling factors for the axes */ - { - /* only multiply the y-axis by the scaling factor to get nice volume-preservation */ - mul_v3_fl(poseMat[1], scaleFac); - - /* set the scaling factors of the x and z axes from... */ - switch (ikData->xzScaleMode) { - case CONSTRAINT_SPLINEIK_XZS_ORIGINAL: - { - /* original scales get used */ - float scale; - - /* x-axis scale */ - scale = len_v3(pchan->pose_mat[0]); - mul_v3_fl(poseMat[0], scale); - /* z-axis scale */ - scale = len_v3(pchan->pose_mat[2]); - mul_v3_fl(poseMat[2], scale); - break; - } - case CONSTRAINT_SPLINEIK_XZS_VOLUMETRIC: - { - /* 'volume preservation' */ - float scale; - - /* calculate volume preservation factor which is - * basically the inverse of the y-scaling factor - */ - if (fabsf(scaleFac) != 0.0f) { - scale = 1.0f / fabsf(scaleFac); - - /* we need to clamp this within sensible values */ - /* NOTE: these should be fine for now, but should get sanitised in future */ - CLAMP(scale, 0.0001f, 100000.0f); - } - else - scale = 1.0f; - - /* apply the scaling */ - mul_v3_fl(poseMat[0], scale); - mul_v3_fl(poseMat[2], scale); - break; - } - } - - /* finally, multiply the x and z scaling by the radius of the curve too, - * to allow automatic scales to get tweaked still - */ - if ((ikData->flag & CONSTRAINT_SPLINEIK_NO_CURVERAD) == 0) { - mul_v3_fl(poseMat[0], radius); - mul_v3_fl(poseMat[2], radius); - } - } - - /* step 5: set the location of the bone in the matrix */ - if (ikData->flag & CONSTRAINT_SPLINEIK_NO_ROOT) { - /* when the 'no-root' option is affected, the chain can retain - * the shape but be moved elsewhere - */ - copy_v3_v3(poseHead, pchan->pose_head); - } - else if (tree->con->enforce < 1.0f) { - /* when the influence is too low - * - blend the positions for the 'root' bone - * - stick to the parent for any other - */ - if (pchan->parent) { - copy_v3_v3(poseHead, pchan->pose_head); - } - else { - /* FIXME: this introduces popping artifacts when we reach 0.0 */ - interp_v3_v3v3(poseHead, pchan->pose_head, poseHead, tree->con->enforce); - } - } - copy_v3_v3(poseMat[3], poseHead); - - /* finally, store the new transform */ - copy_m4_m4(pchan->pose_mat, poseMat); - copy_v3_v3(pchan->pose_head, poseHead); - - /* recalculate tail, as it's now outdated after the head gets adjusted above! */ - BKE_pose_where_is_bone_tail(pchan); - - /* done! */ - pchan->flag |= POSE_DONE; -} - -/* Evaluate the chain starting from the nominated bone */ -static void splineik_execute_tree(Scene *scene, Object *ob, bPoseChannel *pchan_root, float ctime) -{ - tSplineIK_Tree *tree; - - /* for each pose-tree, execute it if it is spline, otherwise just free it */ - while ((tree = pchan_root->siktree.first) != NULL) { - int i; - - /* walk over each bone in the chain, calculating the effects of spline IK - * - the chain is traversed in the opposite order to storage order (i.e. parent to children) - * so that dependencies are correct - */ - for (i = tree->chainlen - 1; i >= 0; i--) { - bPoseChannel *pchan = tree->chain[i]; - splineik_evaluate_bone(tree, scene, ob, pchan, i, ctime); - } - - /* free the tree info specific to SplineIK trees now */ - if (tree->chain) - MEM_freeN(tree->chain); - if (tree->free_points) - MEM_freeN(tree->points); - - /* free this tree */ - BLI_freelinkN(&pchan_root->siktree, tree); - } -} - /* ********************** THE POSE SOLVER ******************* */ /* loc/rot/size to given mat4 */ @@ -2361,7 +1947,7 @@ static void do_strip_modifiers(Scene *scene, Object *armob, Bone *bone, bPoseCha /* validate first */ if (amod->ob && amod->ob->type == OB_CURVE && amod->channel[0]) { - if (strcmp(pchan->name, amod->channel) == 0) { + if (STREQ(pchan->name, amod->channel)) { float mat4[4][4], mat3[3][3]; curve_deform_vector(scene, amod->ob, armob, bone->arm_mat[3], pchan->pose_mat[3], mat3, amod->no_rot_axis); @@ -2374,7 +1960,7 @@ static void do_strip_modifiers(Scene *scene, Object *armob, Bone *bone, bPoseCha break; case ACTSTRIP_MOD_NOISE: { - if (strcmp(pchan->name, amod->channel) == 0) { + if (STREQ(pchan->name, amod->channel)) { float nor[3], loc[3], ofs; float eul[3], size[3], eulo[3], sizeo[3]; @@ -2554,7 +2140,7 @@ void BKE_pose_where_is(Scene *scene, Object *ob) * - this is not integrated as an IK plugin, since it should be able * to function in conjunction with standard IK */ - splineik_init_tree(scene, ob, ctime); + BKE_pose_splineik_init_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) { @@ -2564,7 +2150,7 @@ void BKE_pose_where_is(Scene *scene, Object *ob) } /* 4b. if we find a Spline IK root, we handle it separated too */ else if (pchan->flag & POSE_IKSPLINE) { - splineik_execute_tree(scene, ob, pchan, ctime); + BKE_splineik_execute_tree(scene, ob, pchan, ctime); } /* 5. otherwise just call the normal solver */ else if (!(pchan->flag & POSE_DONE)) { @@ -2598,39 +2184,110 @@ static int minmax_armature(Object *ob, float r_min[3], float r_max[3]) return (BLI_listbase_is_empty(&ob->pose->chanbase) == false); } -static void boundbox_armature(Object *ob, float loc[3], float size[3]) +static void boundbox_armature(Object *ob) { BoundBox *bb; float min[3], max[3]; - float mloc[3], msize[3]; if (ob->bb == NULL) - ob->bb = MEM_callocN(sizeof(BoundBox), "Armature boundbox"); + ob->bb = MEM_mallocN(sizeof(BoundBox), "Armature boundbox"); bb = ob->bb; - if (!loc) - loc = mloc; - if (!size) - size = msize; - INIT_MINMAX(min, max); if (!minmax_armature(ob, min, max)) { min[0] = min[1] = min[2] = -1.0f; max[0] = max[1] = max[2] = 1.0f; } - mid_v3_v3v3(loc, min, max); - - size[0] = (max[0] - min[0]) / 2.0f; - size[1] = (max[1] - min[1]) / 2.0f; - size[2] = (max[2] - min[2]) / 2.0f; - BKE_boundbox_init_from_minmax(bb, min, max); } BoundBox *BKE_armature_boundbox_get(Object *ob) { - boundbox_armature(ob, NULL, NULL); + boundbox_armature(ob); return ob->bb; } + +bool BKE_pose_minmax(Object *ob, float r_min[3], float r_max[3], bool use_hidden, bool use_select) +{ + bool changed = false; + + if (ob->pose) { + bArmature *arm = ob->data; + bPoseChannel *pchan; + + for (pchan = ob->pose->chanbase.first; pchan; pchan = pchan->next) { + /* XXX pchan->bone may be NULL for duplicated bones, see duplicateEditBoneObjects() comment + * (editarmature.c:2592)... Skip in this case too! */ + if (pchan->bone && + (!((use_hidden == false) && (PBONE_VISIBLE(arm, pchan->bone) == false)) && + !((use_select == true) && ((pchan->bone->flag & BONE_SELECTED) == 0)))) + { + bPoseChannel *pchan_tx = (pchan->custom && pchan->custom_tx) ? pchan->custom_tx : pchan; + BoundBox *bb_custom = ((pchan->custom) && !(arm->flag & ARM_NO_CUSTOM)) ? + BKE_object_boundbox_get(pchan->custom) : NULL; + if (bb_custom) { + float mat[4][4], smat[4][4]; + scale_m4_fl(smat, PCHAN_CUSTOM_DRAW_SIZE(pchan)); + mul_m4_series(mat, ob->obmat, pchan_tx->pose_mat, smat); + BKE_boundbox_minmax(bb_custom, mat, r_min, r_max); + } + else { + float vec[3]; + mul_v3_m4v3(vec, ob->obmat, pchan_tx->pose_head); + minmax_v3v3_v3(r_min, r_max, vec); + mul_v3_m4v3(vec, ob->obmat, pchan_tx->pose_tail); + minmax_v3v3_v3(r_min, r_max, vec); + } + + changed = true; + } + } + } + + return changed; +} + +/************** Graph evaluation ********************/ + +bPoseChannel *BKE_armature_ik_solver_find_root( + bPoseChannel *pchan, + bKinematicConstraint *data) +{ + bPoseChannel *rootchan = pchan; + if (!(data->flag & CONSTRAINT_IK_TIP)) { + /* Exclude tip from chain. */ + rootchan = rootchan->parent; + } + if (rootchan != NULL) { + int segcount = 0; + while (rootchan->parent) { + /* Continue up chain, until we reach target number of items. */ + segcount++; + if (segcount == data->rootbone) { + break; + } + rootchan = rootchan->parent; + } + } + return rootchan; +} + +bPoseChannel *BKE_armature_splineik_solver_find_root( + bPoseChannel *pchan, + bSplineIKConstraint *data) +{ + bPoseChannel *rootchan = pchan; + int segcount = 0; + BLI_assert(rootchan != NULL); + while (rootchan->parent) { + /* Continue up chain, until we reach target number of items. */ + segcount++; + if (segcount == data->chainlen) { + break; + } + rootchan = rootchan->parent; + } + return rootchan; +} |