diff options
author | Arystanbek Dyussenov <arystan.d@gmail.com> | 2010-09-04 22:49:07 +0400 |
---|---|---|
committer | Arystanbek Dyussenov <arystan.d@gmail.com> | 2010-09-04 22:49:07 +0400 |
commit | 90b464d3728d9ed8ec26fdf59058d236b99dbcd9 (patch) | |
tree | e88cab4fb1358e962b19f658064ca8c9f8d29f5b /source/blender/blenkernel/intern/armature.c | |
parent | 08d02dd04d836976b25793bb1d4c6a86b3f924c7 (diff) | |
parent | b0b787ef38f9947b3176642556f5282eb3518f69 (diff) |
COLLADA branch: merge from trunk -r 28015:31610.soc-2009-chingachgook
Diffstat (limited to 'source/blender/blenkernel/intern/armature.c')
-rw-r--r-- | source/blender/blenkernel/intern/armature.c | 248 |
1 files changed, 75 insertions, 173 deletions
diff --git a/source/blender/blenkernel/intern/armature.c b/source/blender/blenkernel/intern/armature.c index c1998d705ad..41821f34ba8 100644 --- a/source/blender/blenkernel/intern/armature.c +++ b/source/blender/blenkernel/intern/armature.c @@ -45,6 +45,7 @@ #include "DNA_meshdata_types.h" #include "DNA_nla_types.h" #include "DNA_scene_types.h" +#include "DNA_object_types.h" #include "BKE_animsys.h" #include "BKE_armature.h" @@ -54,6 +55,7 @@ #include "BKE_curve.h" #include "BKE_depsgraph.h" #include "BKE_DerivedMesh.h" +#include "BKE_deform.h" #include "BKE_displist.h" #include "BKE_global.h" #include "BKE_idprop.h" @@ -65,10 +67,6 @@ #include "BIK_api.h" #include "BKE_sketch.h" -#ifdef HAVE_CONFIG_H -#include <config.h> -#endif - /* **************** Generic Functions, data level *************** */ bArmature *add_armature(char *name) @@ -248,131 +246,20 @@ Bone *get_named_bone (bArmature *arm, const char *name) return bone; } - -#define IS_SEPARATOR(a) (a=='.' || a==' ' || a=='-' || a=='_') - -/* finds the best possible flipped name. For renaming; check for unique names afterwards */ -/* if strip_number: removes number extensions */ -void bone_flip_name (char *name, int strip_number) -{ - int len; - char prefix[128]={""}; /* The part before the facing */ - char suffix[128]={""}; /* The part after the facing */ - char replace[128]={""}; /* The replacement string */ - char number[128]={""}; /* The number extension string */ - char *index=NULL; - - len= strlen(name); - if(len<3) return; // we don't do names like .R or .L - - /* We first check the case with a .### extension, let's find the last period */ - if(isdigit(name[len-1])) { - index= strrchr(name, '.'); // last occurrence - if (index && isdigit(index[1]) ) { // doesnt handle case bone.1abc2 correct..., whatever! - if(strip_number==0) - strcpy(number, index); - *index= 0; - len= strlen(name); - } - } - - strcpy (prefix, name); - - /* first case; separator . - _ with extensions r R l L */ - if( IS_SEPARATOR(name[len-2]) ) { - switch(name[len-1]) { - case 'l': - prefix[len-1]= 0; - strcpy(replace, "r"); - break; - case 'r': - prefix[len-1]= 0; - strcpy(replace, "l"); - break; - case 'L': - prefix[len-1]= 0; - strcpy(replace, "R"); - break; - case 'R': - prefix[len-1]= 0; - strcpy(replace, "L"); - break; - } - } - /* case; beginning with r R l L , with separator after it */ - else if( IS_SEPARATOR(name[1]) ) { - switch(name[0]) { - case 'l': - strcpy(replace, "r"); - strcpy(suffix, name+1); - prefix[0]= 0; - break; - case 'r': - strcpy(replace, "l"); - strcpy(suffix, name+1); - prefix[0]= 0; - break; - case 'L': - strcpy(replace, "R"); - strcpy(suffix, name+1); - prefix[0]= 0; - break; - case 'R': - strcpy(replace, "L"); - strcpy(suffix, name+1); - prefix[0]= 0; - break; - } - } - else if(len > 5) { - /* hrms, why test for a separator? lets do the rule 'ultimate left or right' */ - index = BLI_strcasestr(prefix, "right"); - if (index==prefix || index==prefix+len-5) { - if(index[0]=='r') - strcpy (replace, "left"); - else { - if(index[1]=='I') - strcpy (replace, "LEFT"); - else - strcpy (replace, "Left"); - } - *index= 0; - strcpy (suffix, index+5); - } - else { - index = BLI_strcasestr(prefix, "left"); - if (index==prefix || index==prefix+len-4) { - if(index[0]=='l') - strcpy (replace, "right"); - else { - if(index[1]=='E') - strcpy (replace, "RIGHT"); - else - strcpy (replace, "Right"); - } - *index= 0; - strcpy (suffix, index+4); - } - } - } - - sprintf (name, "%s%s%s%s", prefix, replace, suffix, number); -} - /* Finds the best possible extension to the name on a particular axis. (For renaming, check for unique names afterwards) * This assumes that bone names are at most 32 chars long! * strip_number: removes number extensions (TODO: not used) * axis: the axis to name on * head/tail: the head/tail co-ordinate of the bone on the specified axis */ -void bone_autoside_name (char *name, int strip_number, short axis, float head, float tail) +int bone_autoside_name (char *name, int strip_number, short axis, float head, float tail) { unsigned int len; char basename[32]={""}; char extension[5]={""}; len= strlen(name); - if (len == 0) return; + if (len == 0) return 0; strcpy(basename, name); /* Figure out extension to append: @@ -466,9 +353,15 @@ void bone_autoside_name (char *name, int strip_number, short axis, float head, f if ((32 - len) < strlen(extension) + 1) { /* add 1 for the '.' */ strncpy(name, basename, len-strlen(extension)); } + + sprintf(name, "%s.%s", basename, extension); + + return 1; } - sprintf(name, "%s.%s", basename, extension); + else { + return 0; + } } /* ************* B-Bone support ******************* */ @@ -684,11 +577,11 @@ Mat4 *b_bone_spline_setup(bPoseChannel *pchan, int rest) /* ************ Armature Deform ******************* */ -static void pchan_b_bone_defmats(bPoseChannel *pchan, int use_quaternion, int rest_def) +static void pchan_b_bone_defmats(bPoseChannel *pchan, int use_quaternion) { Bone *bone= pchan->bone; Mat4 *b_bone= b_bone_spline_setup(pchan, 0); - Mat4 *b_bone_rest= (rest_def)? NULL: b_bone_spline_setup(pchan, 1); + Mat4 *b_bone_rest= b_bone_spline_setup(pchan, 1); Mat4 *b_bone_mats; DualQuat *b_bone_dual_quats= NULL; float tmat[4][4]; @@ -715,10 +608,7 @@ static void pchan_b_bone_defmats(bPoseChannel *pchan, int use_quaternion, int re unit_m4(tmat); for(a=0; a<bone->segments; a++) { - if(b_bone_rest) - invert_m4_m4(tmat, b_bone_rest[a].mat); - else - tmat[3][1] = -a*(bone->length/(float)bone->segments); + invert_m4_m4(tmat, b_bone_rest[a].mat); mul_serie_m4(b_bone_mats[a+1].mat, pchan->chan_mat, bone->arm_mat, b_bone[a].mat, tmat, b_bone_mats[0].mat, NULL, NULL, NULL); @@ -847,9 +737,8 @@ static float dist_bone_deform(bPoseChannel *pchan, float *vec, DualQuat *dq, flo mul_m4_v3(pchan->chan_mat, cop); // Make this a delta from the base position - sub_v3_v3v3(cop, cop, co); - cop[0]*=fac; cop[1]*=fac; cop[2]*=fac; - add_v3_v3v3(vec, vec, cop); + sub_v3_v3(cop, co); + madd_v3_v3fl(vec, cop, fac); if(mat) pchan_deform_mat_add(pchan, fac, bbonemat, mat); @@ -917,12 +806,11 @@ void armature_deform_verts(Object *armOb, Object *target, DerivedMesh *dm, float obinv[4][4], premat[4][4], postmat[4][4]; int use_envelope = deformflag & ARM_DEF_ENVELOPE; int use_quaternion = deformflag & ARM_DEF_QUATERNION; - int bbone_rest_def = deformflag & ARM_DEF_B_BONE_REST; int invert_vgroup= deformflag & ARM_DEF_INVERT_VGROUP; int numGroups = 0; /* safety for vertexgroup index overflow */ int i, target_totvert = 0; /* safety for vertexgroup overflow */ int use_dverts = 0; - int armature_def_nr = -1; + int armature_def_nr; int totchan; if(arm->edbo) return; @@ -944,7 +832,7 @@ void armature_deform_verts(Object *armOb, Object *target, DerivedMesh *dm, for(pchan = armOb->pose->chanbase.first; pchan; pchan = pchan->next) { if(!(pchan->bone->flag & BONE_NO_DEFORM)) { if(pchan->bone->segments > 1) - pchan_b_bone_defmats(pchan, use_quaternion, bbone_rest_def); + pchan_b_bone_defmats(pchan, use_quaternion); if(use_quaternion) { pchan->dual_quat= &dualquats[totchan++]; @@ -954,26 +842,28 @@ void armature_deform_verts(Object *armOb, Object *target, DerivedMesh *dm, } /* get the def_nr for the overall armature vertex group if present */ - for(i = 0, dg = target->defbase.first; dg; i++, dg = dg->next) - if(defgrp_name && strcmp(defgrp_name, dg->name) == 0) - armature_def_nr = i; - + armature_def_nr= defgroup_name_index(target, defgrp_name); + + if(ELEM(target->type, OB_MESH, OB_LATTICE)) { + numGroups = BLI_countlist(&target->defbase); + + if(target->type==OB_MESH) { + Mesh *me= target->data; + dverts = me->dvert; + if(dverts) + target_totvert = me->totvert; + } + else { + Lattice *lt= target->data; + dverts = lt->dvert; + if(dverts) + target_totvert = lt->pntsu*lt->pntsv*lt->pntsw; + } + } + /* get a vertex-deform-index to posechannel array */ if(deformflag & ARM_DEF_VGROUP) { if(ELEM(target->type, OB_MESH, OB_LATTICE)) { - numGroups = BLI_countlist(&target->defbase); - - if(target->type==OB_MESH) { - Mesh *me= target->data; - dverts = me->dvert; - target_totvert = me->totvert; - } - else { - Lattice *lt= target->data; - dverts = lt->dvert; - if(dverts) - target_totvert = lt->pntsu*lt->pntsv*lt->pntsw; - } /* if we have a DerivedMesh, only use dverts if it has them */ if(dm) if(dm->getVertData(dm, 0, CD_MDEFORMVERT)) @@ -1105,9 +995,9 @@ void armature_deform_verts(Object *armOb, Object *target, DerivedMesh *dm, if(armature_weight != 1.0f) { VECCOPY(dco, co); mul_v3m3_dq( dco, (defMats)? summat: NULL,dq); - sub_v3_v3v3(dco, dco, co); + sub_v3_v3(dco, co); mul_v3_fl(dco, armature_weight); - add_v3_v3v3(co, co, dco); + add_v3_v3(co, dco); } else mul_v3m3_dq( co, (defMats)? summat: NULL,dq); @@ -1393,9 +1283,8 @@ void vec_roll_to_mat3(float *vec, float roll, float mat[][3]) float nor[3], axis[3], target[3]={0,1,0}; float theta; float rMatrix[3][3], bMatrix[3][3]; - - VECCOPY (nor, vec); - normalize_v3(nor); + + normalize_v3_v3(nor, vec); /* Find Axis & Amount for bone matrix*/ cross_v3_v3v3(axis,target,nor); @@ -1564,9 +1453,11 @@ static void pose_proxy_synchronize(Object *ob, Object *from, int layer_protected * 1. extract constraints not from proxy (CONSTRAINT_PROXY_LOCAL) from pchan's constraints * 2. copy proxy-pchan's constraints on-to new * 3. add extracted local constraints back on top + * + * note for copy_constraints: when copying constraints, disable 'do_extern' otherwise we get the libs direct linked in this blend. */ extract_proxylocal_constraints(&proxylocal_constraints, &pchan->constraints); - copy_constraints(&pchanw.constraints, &pchanp->constraints); + copy_constraints(&pchanw.constraints, &pchanp->constraints, FALSE); addlisttolist(&pchanw.constraints, &proxylocal_constraints); /* constraints - set target ob pointer to own object */ @@ -1695,6 +1586,8 @@ void armature_rebuild_pose(Object *ob, bArmature *arm) ob->pose->flag &= ~POSE_RECALC; ob->pose->flag |= POSE_WAS_REBUILT; + + make_pose_channels_hash(ob->pose); } @@ -1769,20 +1662,13 @@ static void splineik_init_tree_from_pchan(Scene *scene, Object *ob, bPoseChannel /* 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; pchan= pchan->parent) { + 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]; - - /* check if we've gotten the number of bones required yet (after incrementing the count first) - * NOTE: the 255 limit here is rather ugly, but the standard IK does this too! - */ - segcount++; - if ((segcount == ikData->chainlen) || (segcount > 255)) - break; } if (segcount == 0) @@ -1940,7 +1826,7 @@ static void splineik_evaluate_bone(tSplineIK_Tree *tree, Scene *scene, Object *o } /* tail endpoint */ - if ( where_on_path(ikData->tar, tree->points[index], vec, dir, NULL, &rad) ) { + 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) */ @@ -1956,7 +1842,7 @@ static void splineik_evaluate_bone(tSplineIK_Tree *tree, Scene *scene, Object *o } /* head endpoint */ - if ( where_on_path(ikData->tar, tree->points[index+1], vec, dir, NULL, &rad) ) { + 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) */ @@ -2005,6 +1891,11 @@ static void splineik_evaluate_bone(tSplineIK_Tree *tree, Scene *scene, Object *o rangle= dot_v3v3(rmat[1], splineVec); rangle= acos( MAX2(-1.0f, MIN2(1.0f, 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 */ @@ -2051,7 +1942,7 @@ static void splineik_evaluate_bone(tSplineIK_Tree *tree, Scene *scene, Object *o /* we need to clamp this within sensible values */ // NOTE: these should be fine for now, but should get sanitised in future - scale= MIN2( MAX2(scale, 0.0001) , 100000); + scale= MIN2(MAX2(scale, 0.0001) , 100000); } else scale= 1.0f; @@ -2072,13 +1963,26 @@ static void splineik_evaluate_bone(tSplineIK_Tree *tree, Scene *scene, Object *o } } - /* step 5: set the location of the bone in the matrix - * - when the 'no-root' option is affected, the chain can retain - * the shape but be moved elsewhere - */ + /* 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 + */ VECCOPY(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) { + VECCOPY(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); + } + } VECCOPY(poseMat[3], poseHead); /* finally, store the new transform */ @@ -2110,8 +2014,6 @@ static void splineik_execute_tree(Scene *scene, Object *ob, bPoseChannel *pchan_ splineik_evaluate_bone(tree, scene, ob, pchan, i, ctime); } - // TODO: if another pass is needed to ensure the validity of the chain after blending, it should go here - /* free the tree info specific to SplineIK trees now */ if (tree->chain) MEM_freeN(tree->chain); if (tree->free_points) MEM_freeN(tree->points); @@ -2261,7 +2163,7 @@ static void do_strip_modifiers(Scene *scene, Object *armob, Bone *bone, bPoseCha nor[0] = BLI_gNoise(amod->noisesize, size[0]+ofs, size[1], size[2], 0, 0) - ofs; nor[1] = BLI_gNoise(amod->noisesize, size[0], size[1]+ofs, size[2], 0, 0) - ofs; nor[2] = BLI_gNoise(amod->noisesize, size[0], size[1], size[2]+ofs, 0, 0) - ofs; - add_v3_v3v3(size, size, nor); + add_v3_v3(size, nor); if (sizeo[0] != 0) mul_v3_fl(pchan->pose_mat[0], size[0] / sizeo[0]); @@ -2277,7 +2179,7 @@ static void do_strip_modifiers(Scene *scene, Object *armob, Bone *bone, bPoseCha nor[2] = BLI_gNoise(amod->noisesize, eul[0], eul[1], eul[2]+ofs, 0, 0) - ofs; compatible_eul(nor, eulo); - add_v3_v3v3(eul, eul, nor); + add_v3_v3(eul, nor); compatible_eul(eul, eulo); loc_eul_size_to_mat4(pchan->pose_mat, loc, eul, size); @@ -2380,7 +2282,7 @@ void where_is_pose_bone(Scene *scene, Object *ob, bPoseChannel *pchan, float cti /* only rootbones get the cyclic offset (unless user doesn't want that) */ if ((bone->flag & BONE_NO_CYCLICOFFSET) == 0) - add_v3_v3v3(pchan->pose_mat[3], pchan->pose_mat[3], ob->pose->cyclic_offset); + add_v3_v3(pchan->pose_mat[3], ob->pose->cyclic_offset); } if(do_extra) { |