/* Makes a copy of the current pose for restoration purposes - doesn't do constraints currently */ static void poselib_backup_posecopy(tPoseLib_PreviewData *pld) { bActionGroup *agrp; bPoseChannel *pchan; /* for each posechannel that has an actionchannel in */ for (agrp = pld->act->groups.first; agrp; agrp = agrp->next) { /* try to find posechannel */ pchan = BKE_pose_channel_find_name(pld->pose, agrp->name); /* backup data if available */ if (pchan) { tPoseLib_Backup *plb; /* store backup */ plb = MEM_callocN(sizeof(tPoseLib_Backup), "tPoseLib_Backup"); plb->pchan = pchan; memcpy(&plb->olddata, plb->pchan, sizeof(bPoseChannel)); if (pchan->prop) plb->oldprops = IDP_CopyProperty(pchan->prop); BLI_addtail(&pld->backups, plb); /* mark as being affected */ if ((pchan->bone) && (pchan->bone->flag & BONE_SELECTED)) pld->selcount++; pld->totcount++; } } }
/* Returns total selected vgroups, * wpi.defbase_sel is assumed malloc'd, all values are set */ bool *BKE_objdef_selected_get(Object *ob, int defbase_tot, int *r_dg_flags_sel_tot) { bool *dg_selection = MEM_mallocN(defbase_tot * sizeof(bool), __func__); bDeformGroup *defgroup; unsigned int i; Object *armob = BKE_object_pose_armature_get(ob); (*r_dg_flags_sel_tot) = 0; if (armob) { bPose *pose = armob->pose; for (i = 0, defgroup = ob->defbase.first; i < defbase_tot && defgroup; defgroup = defgroup->next, i++) { bPoseChannel *pchan = BKE_pose_channel_find_name(pose, defgroup->name); if (pchan && (pchan->bone->flag & BONE_SELECTED)) { dg_selection[i] = TRUE; (*r_dg_flags_sel_tot) += 1; } else { dg_selection[i] = FALSE; } } } else { memset(dg_selection, FALSE, sizeof(*dg_selection) * defbase_tot); } return dg_selection; }
static int buttons_context_path_pose_bone(ButsContextPath *path) { PointerRNA *ptr = &path->ptr[path->len - 1]; /* if we already have a (pinned) PoseBone, we're done */ if (RNA_struct_is_a(ptr->type, &RNA_PoseBone)) { return 1; } /* if we have an armature, get the active bone */ if (buttons_context_path_object(path)) { Object *ob = path->ptr[path->len - 1].data; bArmature *arm = ob->data; /* path->ptr[path->len-1].data - works too */ if (ob->type != OB_ARMATURE || arm->edbo) { return 0; } else { if (arm->act_bone) { bPoseChannel *pchan = BKE_pose_channel_find_name(ob->pose, arm->act_bone->name); if (pchan) { RNA_pointer_create(&ob->id, &RNA_PoseBone, pchan, &path->ptr[path->len]); path->len++; return 1; } } } } /* no path to a bone possible */ return 0; }
/* calculate difference matrix */ void ED_gpencil_parent_location(bGPDlayer *gpl, float diff_mat[4][4]) { Object *ob = gpl->parent; if (ob == NULL) { unit_m4(diff_mat); return; } else { if ((gpl->partype == PAROBJECT) || (gpl->partype == PARSKEL)) { mul_m4_m4m4(diff_mat, ob->obmat, gpl->inverse); return; } else if (gpl->partype == PARBONE) { bPoseChannel *pchan = BKE_pose_channel_find_name(ob->pose, gpl->parsubstr); if (pchan) { float tmp_mat[4][4]; mul_m4_m4m4(tmp_mat, ob->obmat, pchan->pose_mat); mul_m4_m4m4(diff_mat, tmp_mat, gpl->inverse); } else { mul_m4_m4m4(diff_mat, ob->obmat, gpl->inverse); /* if bone not found use object (armature) */ } return; } else { unit_m4(diff_mat); /* not defined type */ } } }
void AnimationExporter::sample_and_write_bone_animation_matrix(Object *ob_arm, Bone *bone) { bArmature *arm = (bArmature *)ob_arm->data; int flag = arm->flag; std::vector<float> fra; //char prefix[256]; FCurve *fcu = (FCurve *)ob_arm->adt->action->curves.first; while (fcu) { std::string bone_name = getObjectBoneName(ob_arm, fcu); int val = BLI_strcasecmp((char *)bone_name.c_str(), bone->name); if (val == 0) break; fcu = fcu->next; } if (!(fcu)) return; bPoseChannel *pchan = BKE_pose_channel_find_name(ob_arm->pose, bone->name); if (!pchan) return; find_frames(ob_arm, fra); if (flag & ARM_RESTPOS) { arm->flag &= ~ARM_RESTPOS; BKE_pose_where_is(scene, ob_arm); } if (fra.size()) { dae_baked_animation(fra, ob_arm, bone); } if (flag & ARM_RESTPOS) arm->flag = flag; BKE_pose_where_is(scene, ob_arm); }
/* perform syncing updates for Action Groups */ static void animchan_sync_group(bAnimContext *ac, bAnimListElem *ale, bActionGroup **active_agrp) { bActionGroup *agrp = (bActionGroup *)ale->data; ID *owner_id = ale->id; /* major priority is selection status * so we need both a group and an owner */ if (ELEM(NULL, agrp, owner_id)) return; /* for standard Objects, check if group is the name of some bone */ if (GS(owner_id->name) == ID_OB) { Object *ob = (Object *)owner_id; /* check if there are bones, and whether the name matches any * NOTE: this feature will only really work if groups by default contain the F-Curves for a single bone */ if (ob->pose) { bPoseChannel *pchan = BKE_pose_channel_find_name(ob->pose, agrp->name); bArmature *arm = ob->data; if (pchan) { bActionGroup *bgrp; /* if one matches, sync the selection status */ if ((pchan->bone) && (pchan->bone->flag & BONE_SELECTED)) agrp->flag |= AGRP_SELECTED; else agrp->flag &= ~AGRP_SELECTED; /* also sync active group status */ if ((ob == ac->obact) && (pchan->bone == arm->act_bone)) { /* if no previous F-Curve has active flag, then we're the first and only one to get it */ if (*active_agrp == NULL) { agrp->flag |= AGRP_ACTIVE; *active_agrp = agrp; } else { /* someone else has already taken it - set as not active */ agrp->flag &= ~AGRP_ACTIVE; } } else { /* this can't possibly be active now */ agrp->flag &= ~AGRP_ACTIVE; } /* sync group colors */ bgrp = (bActionGroup *)BLI_findlink(&ob->pose->agroups, (pchan->agrp_index - 1)); if (bgrp) { agrp->customCol = bgrp->customCol; action_group_colors_sync(agrp, bgrp); } } } } }
/* Applies the appropriate stored pose from the pose-library to the current pose * - assumes that a valid object, with a poselib has been supplied * - gets the string to print in the header * - this code is based on the code for extract_pose_from_action in blenkernel/action.c */ static void poselib_apply_pose(tPoseLib_PreviewData *pld) { PointerRNA *ptr = &pld->rna_ptr; bArmature *arm = pld->arm; bPose *pose = pld->pose; bPoseChannel *pchan; bAction *act = pld->act; bActionGroup *agrp; KeyframeEditData ked = {{NULL}}; KeyframeEditFunc group_ok_cb; int frame = 1; /* get the frame */ if (pld->marker) frame = pld->marker->frame; else return; /* init settings for testing groups for keyframes */ group_ok_cb = ANIM_editkeyframes_ok(BEZT_OK_FRAMERANGE); ked.f1 = ((float)frame) - 0.5f; ked.f2 = ((float)frame) + 0.5f; /* start applying - only those channels which have a key at this point in time! */ for (agrp = act->groups.first; agrp; agrp = agrp->next) { /* check if group has any keyframes */ if (ANIM_animchanneldata_keyframes_loop(&ked, NULL, agrp, ALE_GROUP, NULL, group_ok_cb, NULL)) { /* has keyframe on this frame, so try to get a PoseChannel with this name */ pchan = BKE_pose_channel_find_name(pose, agrp->name); if (pchan) { short ok = 0; /* check if this bone should get any animation applied */ if (pld->selcount == 0) { /* if no bones are selected, then any bone is ok */ ok = 1; } else if (pchan->bone) { /* only ok if bone is visible and selected */ if ((pchan->bone->flag & BONE_SELECTED) && (pchan->bone->flag & BONE_HIDDEN_P) == 0 && (pchan->bone->layer & arm->layer)) { ok = 1; } } if (ok) animsys_evaluate_action_group(ptr, act, agrp, NULL, (float)frame); } } } }
void postEditBoneDuplicate(struct ListBase *editbones, Object *ob) { if (ob->pose == NULL) { return; } BKE_pose_channels_hash_free(ob->pose); BKE_pose_channels_hash_make(ob->pose); GHash *name_map = BLI_ghash_str_new(__func__); for (EditBone *ebone_src = editbones->first; ebone_src; ebone_src = ebone_src->next) { EditBone *ebone_dst = ebone_src->temp.ebone; if (!ebone_dst) { ebone_dst = ED_armature_bone_get_mirrored(editbones, ebone_src); } if (ebone_dst) { BLI_ghash_insert(name_map, ebone_src->name, ebone_dst->name); } } for (EditBone *ebone_src = editbones->first; ebone_src; ebone_src = ebone_src->next) { EditBone *ebone_dst = ebone_src->temp.ebone; if (ebone_dst) { bPoseChannel *pchan_src = BKE_pose_channel_find_name(ob->pose, ebone_src->name); if (pchan_src) { bPoseChannel *pchan_dst = BKE_pose_channel_find_name(ob->pose, ebone_dst->name); if (pchan_dst) { if (pchan_src->custom_tx) { pchan_dst->custom_tx = pchan_duplicate_map(ob->pose, name_map, pchan_src->custom_tx); } if (pchan_src->bbone_prev) { pchan_dst->bbone_prev = pchan_duplicate_map(ob->pose, name_map, pchan_src->bbone_prev); } if (pchan_src->bbone_next) { pchan_dst->bbone_next = pchan_duplicate_map(ob->pose, name_map, pchan_src->bbone_next); } } } } } BLI_ghash_free(name_map, NULL, NULL); }
static void matrix_from_obj_pchan(float mat[4][4], Object *ob, const char *bonename) { bPoseChannel *pchan = BKE_pose_channel_find_name(ob->pose, bonename); if (pchan) { mul_m4_m4m4(mat, ob->obmat, pchan->pose_mat); } else { copy_m4_m4(mat, ob->obmat); } }
/** * \see #ED_armature_bone_get_mirrored (edit-mode, matching function) */ bPoseChannel *BKE_pose_channel_get_mirrored(const bPose *pose, const char *name) { char name_flip[MAXBONENAME]; BKE_deform_flip_side_name(name_flip, name, false); if (!STREQ(name_flip, name)) { return BKE_pose_channel_find_name(pose, name_flip); } return NULL; }
bool BL_ArmatureObject::GetBoneMatrix(Bone* bone, MT_Matrix4x4& matrix) { bPoseChannel *pchan; ApplyPose(); pchan = BKE_pose_channel_find_name(m_objArma->pose, bone->name); if (pchan) matrix.setValue(&pchan->pose_mat[0][0]); RestorePose(); return (pchan != NULL); }
static int pose_select_constraint_target_exec(bContext *C, wmOperator *UNUSED(op)) { Object *ob = BKE_object_pose_armature_get(CTX_data_active_object(C)); bArmature *arm = (bArmature *)ob->data; bConstraint *con; int found = 0; CTX_DATA_BEGIN (C, bPoseChannel *, pchan, visible_pose_bones) { if (pchan->bone->flag & BONE_SELECTED) { for (con = pchan->constraints.first; con; con = con->next) { bConstraintTypeInfo *cti = BKE_constraint_get_typeinfo(con); ListBase targets = {NULL, NULL}; bConstraintTarget *ct; if (cti && cti->get_constraint_targets) { cti->get_constraint_targets(con, &targets); for (ct = targets.first; ct; ct = ct->next) { if ((ct->tar == ob) && (ct->subtarget[0])) { bPoseChannel *pchanc = BKE_pose_channel_find_name(ob->pose, ct->subtarget); if ((pchanc) && !(pchanc->bone->flag & BONE_UNSELECTABLE)) { pchanc->bone->flag |= BONE_SELECTED | BONE_TIPSEL | BONE_ROOTSEL; found = 1; } } } if (cti->flush_constraint_targets) cti->flush_constraint_targets(con, &targets, 1); } } } } CTX_DATA_END; if (!found) return OPERATOR_CANCELLED; /* updates */ WM_event_add_notifier(C, NC_OBJECT | ND_BONE_SELECT, ob); if (arm->flag & ARM_HAS_VIZ_DEPS) { /* mask modifier ('armature' mode), etc. */ DAG_id_tag_update(&ob->id, OB_RECALC_DATA); } return OPERATOR_FINISHED; }
void AnimationExporter::sample_animation(float *v, std::vector<float> &frames, int type, Bone *bone, Object *ob_arm, bPoseChannel *pchan) { bPoseChannel *parchan = NULL; bPose *pose = ob_arm->pose; pchan = BKE_pose_channel_find_name(pose, bone->name); if (!pchan) return; parchan = pchan->parent; enable_fcurves(ob_arm->adt->action, bone->name); std::vector<float>::iterator it; for (it = frames.begin(); it != frames.end(); it++) { float mat[4][4], ipar[4][4]; float ctime = BKE_scene_frame_get_from_ctime(scene, *it); BKE_animsys_evaluate_animdata(scene, &ob_arm->id, ob_arm->adt, ctime, ADT_RECALC_ANIM); BKE_pose_where_is_bone(scene, ob_arm, pchan, ctime, 1); // compute bone local mat if (bone->parent) { invert_m4_m4(ipar, parchan->pose_mat); mult_m4_m4m4(mat, ipar, pchan->pose_mat); } else copy_m4_m4(mat, pchan->pose_mat); switch (type) { case 0: mat4_to_eul(v, mat); break; case 1: mat4_to_size(v, mat); break; case 2: copy_v3_v3(v, mat[3]); break; } v += 3; } enable_fcurves(ob_arm->adt->action, NULL); }
/** * Allocate a new pose on the heap, and copy the src pose and it's channels * into the new pose. *dst is set to the newly allocated structure, and assumed to be NULL. * * \param dst Should be freed already, makes entire duplicate. */ void BKE_pose_copy_data(bPose **dst, bPose *src, const bool copy_constraints) { bPose *outPose; bPoseChannel *pchan; ListBase listb; if (!src) { *dst = NULL; return; } 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); outPose->avs = src->avs; for (pchan = outPose->chanbase.first; pchan; pchan = pchan->next) { if (pchan->custom) { id_us_plus(&pchan->custom->id); } /* warning, O(n2) here, but it's a rarely used feature. */ if (pchan->custom_tx) { pchan->custom_tx = BKE_pose_channel_find_name(outPose, pchan->custom_tx->name); } if (copy_constraints) { BKE_constraints_copy(&listb, &pchan->constraints, true); // BKE_constraints_copy NULLs listb pchan->constraints = listb; pchan->mpath = NULL; /* motion paths should not get copied yet... */ } if (pchan->prop) { pchan->prop = IDP_CopyProperty(pchan->prop); } } /* for now, duplicate Bone Groups too when doing this */ if (copy_constraints) { BLI_duplicatelist(&outPose->agroups, &src->agroups); } *dst = outPose; }
/** * Helper function for #postEditBoneDuplicate, * return the destination pchan from the original. */ static bPoseChannel *pchan_duplicate_map(const bPose *pose, GHash *name_map, bPoseChannel *pchan_src) { bPoseChannel *pchan_dst = NULL; const char *name_src = pchan_src->name; const char *name_dst = BLI_ghash_lookup(name_map, name_src); if (name_dst) { pchan_dst = BKE_pose_channel_find_name(pose, name_dst); } if (pchan_dst == NULL) { pchan_dst = pchan_src; } return pchan_dst; }
static int bone_skinnable_cb(Object *ob, Bone *bone, void *datap) { /* Bones that are deforming * are regarded to be "skinnable" and are eligible for * auto-skinning. * * This function performs 2 functions: * * a) It returns 1 if the bone is skinnable. * If we loop over all bones with this * function, we can count the number of * skinnable bones. * b) If the pointer data is non null, * it is treated like a handle to a * bone pointer -- the bone pointer * is set to point at this bone, and * the pointer the handle points to * is incremented to point to the * next member of an array of pointers * to bones. This way we can loop using * this function to construct an array of * pointers to bones that point to all * skinnable bones. */ Bone ***hbone; int a, segments; struct { Object *armob; void *list; int heat; } *data = datap; if (!(ob->mode & OB_MODE_WEIGHT_PAINT) || !(bone->flag & BONE_HIDDEN_P)) { if (!(bone->flag & BONE_NO_DEFORM)) { if (data->heat && data->armob->pose && BKE_pose_channel_find_name(data->armob->pose, bone->name)) segments = bone->segments; else segments = 1; if (data->list != NULL) { hbone = (Bone ***) &data->list; for (a = 0; a < segments; a++) { **hbone = bone; ++*hbone; } } return segments; } } return 0; }
/* both poses should be in sync */ bool BKE_pose_copy_result(bPose *to, bPose *from) { bPoseChannel *pchanto, *pchanfrom; if (to == NULL || from == NULL) { printf("Pose copy error, pose to:%p from:%p\n", (void *)to, (void *)from); /* debug temp */ return false; } if (to == from) { printf("BKE_pose_copy_result source and target are the same\n"); return false; } for (pchanfrom = from->chanbase.first; pchanfrom; pchanfrom = pchanfrom->next) { pchanto = BKE_pose_channel_find_name(to, pchanfrom->name); if (pchanto) { copy_m4_m4(pchanto->pose_mat, pchanfrom->pose_mat); copy_m4_m4(pchanto->chan_mat, pchanfrom->chan_mat); /* used for local constraints */ copy_v3_v3(pchanto->loc, pchanfrom->loc); copy_qt_qt(pchanto->quat, pchanfrom->quat); copy_v3_v3(pchanto->eul, pchanfrom->eul); copy_v3_v3(pchanto->size, pchanfrom->size); copy_v3_v3(pchanto->pose_head, pchanfrom->pose_head); copy_v3_v3(pchanto->pose_tail, pchanfrom->pose_tail); pchanto->roll1 = pchanfrom->roll1; pchanto->roll2 = pchanfrom->roll2; pchanto->curveInX = pchanfrom->curveInX; pchanto->curveInY = pchanfrom->curveInY; pchanto->curveOutX = pchanfrom->curveOutX; pchanto->curveOutY = pchanfrom->curveOutY; pchanto->scaleIn = pchanfrom->scaleIn; pchanto->scaleOut = pchanfrom->scaleOut; pchanto->rotmode = pchanfrom->rotmode; pchanto->flag = pchanfrom->flag; pchanto->protectflag = pchanfrom->protectflag; pchanto->bboneflag = pchanfrom->bboneflag; } } return true; }
/* Auto-keys/tags bones affected by the pose used from the poselib */ static void poselib_keytag_pose(bContext *C, Scene *scene, tPoseLib_PreviewData *pld) { bPose *pose = pld->pose; bPoseChannel *pchan; bAction *act = pld->act; bActionGroup *agrp; KeyingSet *ks = ANIM_get_keyingset_for_autokeying(scene, ANIM_KS_WHOLE_CHARACTER_ID); ListBase dsources = {NULL, NULL}; short autokey = autokeyframe_cfra_can_key(scene, &pld->ob->id); /* start tagging/keying */ for (agrp = act->groups.first; agrp; agrp = agrp->next) { /* only for selected bones unless there aren't any selected, in which case all are included */ pchan = BKE_pose_channel_find_name(pose, agrp->name); if (pchan) { if ((pld->selcount == 0) || ((pchan->bone) && (pchan->bone->flag & BONE_SELECTED))) { if (autokey) { /* add datasource override for the PoseChannel, to be used later */ ANIM_relative_keyingset_add_source(&dsources, &pld->ob->id, &RNA_PoseBone, pchan); /* clear any unkeyed tags */ if (pchan->bone) pchan->bone->flag &= ~BONE_UNKEYED; } else { /* add unkeyed tags */ if (pchan->bone) pchan->bone->flag |= BONE_UNKEYED; } } } } /* perform actual auto-keying now */ if (autokey) { /* insert keyframes for all relevant bones in one go */ ANIM_apply_keyingset(C, &dsources, NULL, ks, MODIFYKEY_MODE_INSERT, (float)CFRA); BLI_freelistN(&dsources); } /* send notifiers for this */ WM_event_add_notifier(C, NC_ANIMATION | ND_KEYFRAME | NA_EDITED, NULL); }
/* don't set windows active in here, is used by renderwin too */ void setviewmatrixview3d(Scene *scene, View3D *v3d, RegionView3D *rv3d) { if (rv3d->persp == RV3D_CAMOB) { /* obs/camera */ if (v3d->camera) { BKE_object_where_is_calc(scene, v3d->camera); obmat_to_viewmat(v3d, rv3d, v3d->camera, 0); } else { quat_to_mat4(rv3d->viewmat, rv3d->viewquat); rv3d->viewmat[3][2] -= rv3d->dist; } } else { /* should be moved to better initialize later on XXX */ if (rv3d->viewlock) ED_view3d_lock(rv3d); quat_to_mat4(rv3d->viewmat, rv3d->viewquat); if (rv3d->persp == RV3D_PERSP) rv3d->viewmat[3][2] -= rv3d->dist; if (v3d->ob_centre) { Object *ob = v3d->ob_centre; float vec[3]; copy_v3_v3(vec, ob->obmat[3]); if (ob->type == OB_ARMATURE && v3d->ob_centre_bone[0]) { bPoseChannel *pchan = BKE_pose_channel_find_name(ob->pose, v3d->ob_centre_bone); if (pchan) { copy_v3_v3(vec, pchan->pose_mat[3]); mul_m4_v3(ob->obmat, vec); } } translate_m4(rv3d->viewmat, -vec[0], -vec[1], -vec[2]); } else if (v3d->ob_centre_cursor) { float vec[3]; copy_v3_v3(vec, give_cursor(scene, v3d)); translate_m4(rv3d->viewmat, -vec[0], -vec[1], -vec[2]); } else { translate_m4(rv3d->viewmat, rv3d->ofs[0], rv3d->ofs[1], rv3d->ofs[2]); } } }
void AnimationExporter::sample_and_write_bone_animation_matrix(Object *ob_arm, Bone *bone) { bArmature *arm = (bArmature *)ob_arm->data; int flag = arm->flag; std::vector<float> fra; //char prefix[256]; //Check if there is a fcurve in the armature for the bone in param //when baking this check is not needed, solve every bone for every frame. /*FCurve *fcu = (FCurve *)ob_arm->adt->action->curves.first; while (fcu) { std::string bone_name = getObjectBoneName(ob_arm, fcu); int val = BLI_strcasecmp((char *)bone_name.c_str(), bone->name); if (val == 0) break; fcu = fcu->next; } if (!(fcu)) return;*/ bPoseChannel *pchan = BKE_pose_channel_find_name(ob_arm->pose, bone->name); if (!pchan) return; //every inserted keyframe of bones. find_frames(ob_arm, fra); if (flag & ARM_RESTPOS) { arm->flag &= ~ARM_RESTPOS; BKE_pose_where_is(scene, ob_arm); } if (fra.size()) { dae_baked_animation(fra, ob_arm, bone); } if (flag & ARM_RESTPOS) arm->flag = flag; BKE_pose_where_is(scene, ob_arm); }
/* reset parent matrix for all layers */ void ED_gpencil_reset_layers_parent(bGPdata *gpd) { bGPDspoint *pt; int i; float diff_mat[4][4]; float cur_mat[4][4]; for (bGPDlayer *gpl = gpd->layers.first; gpl; gpl = gpl->next) { if (gpl->parent != NULL) { /* calculate new matrix */ if ((gpl->partype == PAROBJECT) || (gpl->partype == PARSKEL)) { invert_m4_m4(cur_mat, gpl->parent->obmat); } else if (gpl->partype == PARBONE) { bPoseChannel *pchan = BKE_pose_channel_find_name(gpl->parent->pose, gpl->parsubstr); if (pchan) { float tmp_mat[4][4]; mul_m4_m4m4(tmp_mat, gpl->parent->obmat, pchan->pose_mat); invert_m4_m4(cur_mat, tmp_mat); } } /* only redo if any change */ if (!equals_m4m4(gpl->inverse, cur_mat)) { /* first apply current transformation to all strokes */ ED_gpencil_parent_location(gpl, diff_mat); for (bGPDframe *gpf = gpl->frames.first; gpf; gpf = gpf->next) { for (bGPDstroke *gps = gpf->strokes.first; gps; gps = gps->next) { for (i = 0, pt = gps->points; i < gps->totpoints; i++, pt++) { mul_m4_v3(diff_mat, &pt->x); } } } /* set new parent matrix */ copy_m4_m4(gpl->inverse, cur_mat); } } } }
/* only for real IK, not for auto-IK */ static bool pose_channel_in_IK_chain(Object *ob, bPoseChannel *pchan, int level) { bConstraint *con; Bone *bone; /* No need to check if constraint is active (has influence), * since all constraints with CONSTRAINT_IK_AUTO are active */ for (con = pchan->constraints.first; con; con = con->next) { if (con->type == CONSTRAINT_TYPE_KINEMATIC) { bKinematicConstraint *data = con->data; if ((data->rootbone == 0) || (data->rootbone > level)) { if ((data->flag & CONSTRAINT_IK_AUTO) == 0) return true; } } } for (bone = pchan->bone->childbase.first; bone; bone = bone->next) { pchan = BKE_pose_channel_find_name(ob->pose, bone->name); if (pchan && pose_channel_in_IK_chain(ob, pchan, level + 1)) return true; } return false; }
Bone *ControllerExporter::get_bone_from_defgroup(Object *ob_arm, bDeformGroup *def) { bPoseChannel *pchan = BKE_pose_channel_find_name(ob_arm->pose, def->name); return pchan ? pchan->bone : NULL; }
/* seems messy, but thats what you get with not using pointers but channel names :) */ void ED_armature_bone_rename(bArmature *arm, const char *oldnamep, const char *newnamep) { Object *ob; char newname[MAXBONENAME]; char oldname[MAXBONENAME]; /* names better differ! */ if (strncmp(oldnamep, newnamep, MAXBONENAME)) { /* we alter newname string... so make copy */ BLI_strncpy(newname, newnamep, MAXBONENAME); /* we use oldname for search... so make copy */ BLI_strncpy(oldname, oldnamep, MAXBONENAME); /* now check if we're in editmode, we need to find the unique name */ if (arm->edbo) { EditBone *eBone = ED_armature_bone_find_name(arm->edbo, oldname); if (eBone) { unique_editbone_name(arm->edbo, newname, NULL); BLI_strncpy(eBone->name, newname, MAXBONENAME); } else { return; } } else { Bone *bone = BKE_armature_find_bone_name(arm, oldname); if (bone) { unique_bone_name(arm, newname); BLI_strncpy(bone->name, newname, MAXBONENAME); } else { return; } } /* do entire dbase - objects */ for (ob = G.main->object.first; ob; ob = ob->id.next) { ModifierData *md; /* we have the object using the armature */ if (arm == ob->data) { Object *cob; /* Rename the pose channel, if it exists */ if (ob->pose) { bPoseChannel *pchan = BKE_pose_channel_find_name(ob->pose, oldname); if (pchan) { GHash *gh = ob->pose->chanhash; /* remove the old hash entry, and replace with the new name */ if (gh) { BLI_assert(BLI_ghash_haskey(gh, pchan->name)); BLI_ghash_remove(gh, pchan->name, NULL, NULL); } BLI_strncpy(pchan->name, newname, MAXBONENAME); if (gh) { BLI_ghash_insert(gh, pchan->name, pchan); } } BLI_assert(BKE_pose_channels_is_valid(ob->pose) == true); } /* Update any object constraints to use the new bone name */ for (cob = G.main->object.first; cob; cob = cob->id.next) { if (cob->constraints.first) constraint_bone_name_fix(ob, &cob->constraints, oldname, newname); if (cob->pose) { bPoseChannel *pchan; for (pchan = cob->pose->chanbase.first; pchan; pchan = pchan->next) { constraint_bone_name_fix(ob, &pchan->constraints, oldname, newname); } } } } /* See if an object is parented to this armature */ if (ob->parent && (ob->parent->data == arm)) { if (ob->partype == PARBONE) { /* bone name in object */ if (!strcmp(ob->parsubstr, oldname)) BLI_strncpy(ob->parsubstr, newname, MAXBONENAME); } } if (modifiers_usesArmature(ob, arm)) { bDeformGroup *dg = defgroup_find_name(ob, oldname); if (dg) { BLI_strncpy(dg->name, newname, MAXBONENAME); } } /* fix modifiers that might be using this name */ for (md = ob->modifiers.first; md; md = md->next) { switch (md->type) { case eModifierType_Hook: { HookModifierData *hmd = (HookModifierData *)md; if (hmd->object && (hmd->object->data == arm)) { if (STREQ(hmd->subtarget, oldname)) BLI_strncpy(hmd->subtarget, newname, MAXBONENAME); } break; } case eModifierType_UVWarp: { UVWarpModifierData *umd = (UVWarpModifierData *)md; if (umd->object_src && (umd->object_src->data == arm)) { if (STREQ(umd->bone_src, oldname)) BLI_strncpy(umd->bone_src, newname, MAXBONENAME); } if (umd->object_dst && (umd->object_dst->data == arm)) { if (STREQ(umd->bone_dst, oldname)) BLI_strncpy(umd->bone_dst, newname, MAXBONENAME); } break; } default: break; } } } /* Fix all animdata that may refer to this bone - we can't just do the ones attached to objects, since * other ID-blocks may have drivers referring to this bone [#29822] */ { BKE_all_animdata_fix_paths_rename(&arm->id, "pose.bones", oldname, newname); } /* correct view locking */ { bScreen *screen; for (screen = G.main->screen.first; screen; screen = screen->id.next) { ScrArea *sa; /* add regions */ for (sa = screen->areabase.first; sa; sa = sa->next) { SpaceLink *sl; for (sl = sa->spacedata.first; sl; sl = sl->next) { if (sl->spacetype == SPACE_VIEW3D) { View3D *v3d = (View3D *)sl; if (v3d->ob_centre && v3d->ob_centre->data == arm) { if (!strcmp(v3d->ob_centre_bone, oldname)) { BLI_strncpy(v3d->ob_centre_bone, newname, MAXBONENAME); } } } } } } } } }
static DerivedMesh *applyModifier(ModifierData *md, Object *ob, DerivedMesh *derivedData, ModifierApplyFlag UNUSED(flag)) { MaskModifierData *mmd = (MaskModifierData *)md; DerivedMesh *dm = derivedData, *result = NULL; GHash *vertHash = NULL, *edgeHash, *polyHash; GHashIterator *hashIter; MDeformVert *dvert = NULL, *dv; int numPolys = 0, numLoops = 0, numEdges = 0, numVerts = 0; int maxVerts, maxEdges, maxPolys; int i; MPoly *mpoly; MLoop *mloop; MPoly *mpoly_new; MLoop *mloop_new; MEdge *medge_new; MVert *mvert_new; int *loop_mapping; /* Overview of Method: * 1. Get the vertices that are in the vertexgroup of interest * 2. Filter out unwanted geometry (i.e. not in vertexgroup), by populating mappings with new vs old indices * 3. Make a new mesh containing only the mapping data */ /* get original number of verts, edges, and faces */ maxVerts = dm->getNumVerts(dm); maxEdges = dm->getNumEdges(dm); maxPolys = dm->getNumPolys(dm); /* check if we can just return the original mesh * - must have verts and therefore verts assigned to vgroups to do anything useful */ if (!(ELEM(mmd->mode, MOD_MASK_MODE_ARM, MOD_MASK_MODE_VGROUP)) || (maxVerts == 0) || (ob->defbase.first == NULL) ) { return derivedData; } /* if mode is to use selected armature bones, aggregate the bone groups */ if (mmd->mode == MOD_MASK_MODE_ARM) { /* --- using selected bones --- */ Object *oba = mmd->ob_arm; bPoseChannel *pchan; bDeformGroup *def; char *bone_select_array; int bone_select_tot = 0; const int defbase_tot = BLI_countlist(&ob->defbase); /* check that there is armature object with bones to use, otherwise return original mesh */ if (ELEM3(NULL, oba, oba->pose, ob->defbase.first)) return derivedData; /* determine whether each vertexgroup is associated with a selected bone or not * - each cell is a boolean saying whether bone corresponding to the ith group is selected * - groups that don't match a bone are treated as not existing (along with the corresponding ungrouped verts) */ bone_select_array = MEM_mallocN(defbase_tot * sizeof(char), "mask array"); for (i = 0, def = ob->defbase.first; def; def = def->next, i++) { pchan = BKE_pose_channel_find_name(oba->pose, def->name); if (pchan && pchan->bone && (pchan->bone->flag & BONE_SELECTED)) { bone_select_array[i] = TRUE; bone_select_tot++; } else { bone_select_array[i] = FALSE; } } /* if no dverts (i.e. no data for vertex groups exists), we've got an * inconsistent situation, so free hashes and return oirginal mesh */ dvert = dm->getVertDataArray(dm, CD_MDEFORMVERT); if (dvert == NULL) { MEM_freeN(bone_select_array); return derivedData; } /* verthash gives mapping from original vertex indices to the new indices (including selected matches only) * key = oldindex, value = newindex */ vertHash = BLI_ghash_int_new("mask vert gh"); /* add vertices which exist in vertexgroups into vertHash for filtering * - dv = for each vertex, what vertexgroups does it belong to * - dw = weight that vertex was assigned to a vertexgroup it belongs to */ for (i = 0, dv = dvert; i < maxVerts; i++, dv++) { MDeformWeight *dw = dv->dw; short found = 0; int j; /* check the groups that vertex is assigned to, and see if it was any use */ for (j = 0; j < dv->totweight; j++, dw++) { if (dw->def_nr < defbase_tot) { if (bone_select_array[dw->def_nr]) { if (dw->weight != 0.0f) { found = TRUE; break; } } } } /* check if include vert in vertHash */ if (mmd->flag & MOD_MASK_INV) { /* if this vert is in the vgroup, don't include it in vertHash */ if (found) continue; } else { /* if this vert isn't in the vgroup, don't include it in vertHash */ if (!found) continue; } /* add to ghash for verts (numVerts acts as counter for mapping) */ BLI_ghash_insert(vertHash, SET_INT_IN_POINTER(i), SET_INT_IN_POINTER(numVerts)); numVerts++; } /* free temp hashes */ MEM_freeN(bone_select_array); } else { /* --- Using Nominated VertexGroup only --- */ int defgrp_index = defgroup_name_index(ob, mmd->vgroup); /* get dverts */ if (defgrp_index != -1) dvert = dm->getVertDataArray(dm, CD_MDEFORMVERT); /* if no vgroup (i.e. dverts) found, return the initial mesh */ if ((defgrp_index == -1) || (dvert == NULL)) return dm; /* hashes for quickly providing a mapping from old to new - use key=oldindex, value=newindex */ vertHash = BLI_ghash_int_new("mask vert2 bh"); /* add vertices which exist in vertexgroup into ghash for filtering */ for (i = 0, dv = dvert; i < maxVerts; i++, dv++) { const int weight_set = defvert_find_weight(dv, defgrp_index) != 0.0f; /* check if include vert in vertHash */ if (mmd->flag & MOD_MASK_INV) { /* if this vert is in the vgroup, don't include it in vertHash */ if (weight_set) continue; } else { /* if this vert isn't in the vgroup, don't include it in vertHash */ if (!weight_set) continue; } /* add to ghash for verts (numVerts acts as counter for mapping) */ BLI_ghash_insert(vertHash, SET_INT_IN_POINTER(i), SET_INT_IN_POINTER(numVerts)); numVerts++; } } /* hashes for quickly providing a mapping from old to new - use key=oldindex, value=newindex */ edgeHash = BLI_ghash_int_new("mask ed2 gh"); polyHash = BLI_ghash_int_new("mask fa2 gh"); mpoly = dm->getPolyArray(dm); mloop = dm->getLoopArray(dm); loop_mapping = MEM_callocN(sizeof(int) * maxPolys, "mask loopmap"); /* overalloc, assume all polys are seen */ /* loop over edges and faces, and do the same thing to * ensure that they only reference existing verts */ for (i = 0; i < maxEdges; i++) { MEdge me; dm->getEdge(dm, i, &me); /* only add if both verts will be in new mesh */ if (BLI_ghash_haskey(vertHash, SET_INT_IN_POINTER(me.v1)) && BLI_ghash_haskey(vertHash, SET_INT_IN_POINTER(me.v2))) { BLI_ghash_insert(edgeHash, SET_INT_IN_POINTER(i), SET_INT_IN_POINTER(numEdges)); numEdges++; } } for (i = 0; i < maxPolys; i++) { MPoly *mp = &mpoly[i]; MLoop *ml = mloop + mp->loopstart; int ok = TRUE; int j; for (j = 0; j < mp->totloop; j++, ml++) { if (!BLI_ghash_haskey(vertHash, SET_INT_IN_POINTER(ml->v))) { ok = FALSE; break; } } /* all verts must be available */ if (ok) { BLI_ghash_insert(polyHash, SET_INT_IN_POINTER(i), SET_INT_IN_POINTER(numPolys)); loop_mapping[numPolys] = numLoops; numPolys++; numLoops += mp->totloop; } } /* now we know the number of verts, edges and faces, * we can create the new (reduced) mesh */ result = CDDM_from_template(dm, numVerts, numEdges, 0, numLoops, numPolys); mpoly_new = CDDM_get_polys(result); mloop_new = CDDM_get_loops(result); medge_new = CDDM_get_edges(result); mvert_new = CDDM_get_verts(result); /* using ghash-iterators, map data into new mesh */ /* vertices */ for (hashIter = BLI_ghashIterator_new(vertHash); !BLI_ghashIterator_isDone(hashIter); BLI_ghashIterator_step(hashIter) ) { MVert source; MVert *dest; int oldIndex = GET_INT_FROM_POINTER(BLI_ghashIterator_getKey(hashIter)); int newIndex = GET_INT_FROM_POINTER(BLI_ghashIterator_getValue(hashIter)); dm->getVert(dm, oldIndex, &source); dest = &mvert_new[newIndex]; DM_copy_vert_data(dm, result, oldIndex, newIndex, 1); *dest = source; } BLI_ghashIterator_free(hashIter); /* edges */ for (hashIter = BLI_ghashIterator_new(edgeHash); !BLI_ghashIterator_isDone(hashIter); BLI_ghashIterator_step(hashIter)) { MEdge source; MEdge *dest; int oldIndex = GET_INT_FROM_POINTER(BLI_ghashIterator_getKey(hashIter)); int newIndex = GET_INT_FROM_POINTER(BLI_ghashIterator_getValue(hashIter)); dm->getEdge(dm, oldIndex, &source); dest = &medge_new[newIndex]; source.v1 = GET_INT_FROM_POINTER(BLI_ghash_lookup(vertHash, SET_INT_IN_POINTER(source.v1))); source.v2 = GET_INT_FROM_POINTER(BLI_ghash_lookup(vertHash, SET_INT_IN_POINTER(source.v2))); DM_copy_edge_data(dm, result, oldIndex, newIndex, 1); *dest = source; } BLI_ghashIterator_free(hashIter); /* faces */ for (hashIter = BLI_ghashIterator_new(polyHash); !BLI_ghashIterator_isDone(hashIter); BLI_ghashIterator_step(hashIter) ) { int oldIndex = GET_INT_FROM_POINTER(BLI_ghashIterator_getKey(hashIter)); int newIndex = GET_INT_FROM_POINTER(BLI_ghashIterator_getValue(hashIter)); MPoly *source = &mpoly[oldIndex]; MPoly *dest = &mpoly_new[newIndex]; int oldLoopIndex = source->loopstart; int newLoopIndex = loop_mapping[newIndex]; MLoop *source_loop = &mloop[oldLoopIndex]; MLoop *dest_loop = &mloop_new[newLoopIndex]; DM_copy_poly_data(dm, result, oldIndex, newIndex, 1); DM_copy_loop_data(dm, result, oldLoopIndex, newLoopIndex, source->totloop); *dest = *source; dest->loopstart = newLoopIndex; for (i = 0; i < source->totloop; i++) { dest_loop[i].v = GET_INT_FROM_POINTER(BLI_ghash_lookup(vertHash, SET_INT_IN_POINTER(source_loop[i].v))); dest_loop[i].e = GET_INT_FROM_POINTER(BLI_ghash_lookup(edgeHash, SET_INT_IN_POINTER(source_loop[i].e))); } } BLI_ghashIterator_free(hashIter); MEM_freeN(loop_mapping); /* why is this needed? - campbell */ /* recalculate normals */ CDDM_calc_normals(result); /* free hashes */ BLI_ghash_free(vertHash, NULL, NULL); BLI_ghash_free(edgeHash, NULL, NULL); BLI_ghash_free(polyHash, NULL, NULL); /* return the new mesh */ return result; }
PyObject* BL_ActionActuator::PyGetChannel(PyObject* value) { PyErr_SetString(PyExc_NotImplementedError, "BL_ActionActuator.getChannel() no longer works, please use BL_ArmatureObject.channels instead"); return NULL; #if 0 // XXX To be removed in a later version (first removed in 2.64) const char *string= _PyUnicode_AsString(value); if (GetParent()->GetGameObjectType() != SCA_IObject::OBJ_ARMATURE) { PyErr_SetString(PyExc_NotImplementedError, "actuator.getChannel(): Only armatures support channels"); return NULL; } if (!string) { PyErr_SetString(PyExc_TypeError, "expected a single string"); return NULL; } bPoseChannel *pchan; if (m_userpose==NULL && m_pose==NULL) { BL_ArmatureObject *obj = (BL_ArmatureObject*)GetParent(); obj->GetPose(&m_pose); /* Get the underlying pose from the armature */ } // BKE_pose_channel_find_name accounts for NULL pose, run on both in case one exists but // the channel doesnt if ( !(pchan=BKE_pose_channel_find_name(m_userpose, string)) && !(pchan=BKE_pose_channel_find_name(m_pose, string)) ) { PyErr_SetString(PyExc_ValueError, "channel doesnt exist"); return NULL; } PyObject *ret = PyTuple_New(3); PyObject *list = PyList_New(3); PyList_SET_ITEM(list, 0, PyFloat_FromDouble(pchan->loc[0])); PyList_SET_ITEM(list, 1, PyFloat_FromDouble(pchan->loc[1])); PyList_SET_ITEM(list, 2, PyFloat_FromDouble(pchan->loc[2])); PyTuple_SET_ITEM(ret, 0, list); list = PyList_New(3); PyList_SET_ITEM(list, 0, PyFloat_FromDouble(pchan->size[0])); PyList_SET_ITEM(list, 1, PyFloat_FromDouble(pchan->size[1])); PyList_SET_ITEM(list, 2, PyFloat_FromDouble(pchan->size[2])); PyTuple_SET_ITEM(ret, 1, list); list = PyList_New(4); PyList_SET_ITEM(list, 0, PyFloat_FromDouble(pchan->quat[0])); PyList_SET_ITEM(list, 1, PyFloat_FromDouble(pchan->quat[1])); PyList_SET_ITEM(list, 2, PyFloat_FromDouble(pchan->quat[2])); PyList_SET_ITEM(list, 3, PyFloat_FromDouble(pchan->quat[3])); PyTuple_SET_ITEM(ret, 2, list); return ret; #if 0 return Py_BuildValue("([fff][fff][ffff])", pchan->loc[0], pchan->loc[1], pchan->loc[2], pchan->size[0], pchan->size[1], pchan->size[2], pchan->quat[0], pchan->quat[1], pchan->quat[2], pchan->quat[3] ); #endif #endif }
std::string ControllerExporter::add_inv_bind_mats_source(Object *ob_arm, ListBase *defbase, const std::string& controller_id) { std::string source_id = controller_id + BIND_POSES_SOURCE_ID_SUFFIX; int totjoint = 0; for (bDeformGroup *def = (bDeformGroup *)defbase->first; def; def = def->next) { if (is_bone_defgroup(ob_arm, def)) totjoint++; } COLLADASW::FloatSourceF source(mSW); source.setId(source_id); source.setArrayId(source_id + ARRAY_ID_SUFFIX); source.setAccessorCount(totjoint); //BLI_listbase_count(defbase)); source.setAccessorStride(16); source.setParameterTypeName(&COLLADASW::CSWC::CSW_VALUE_TYPE_FLOAT4x4); COLLADASW::SourceBase::ParameterNameList ¶m = source.getParameterNameList(); param.push_back("TRANSFORM"); source.prepareToAppendValues(); bPose *pose = ob_arm->pose; bArmature *arm = (bArmature *)ob_arm->data; int flag = arm->flag; // put armature in rest position if (!(arm->flag & ARM_RESTPOS)) { arm->flag |= ARM_RESTPOS; BKE_pose_where_is(scene, ob_arm); } for (bDeformGroup *def = (bDeformGroup *)defbase->first; def; def = def->next) { if (is_bone_defgroup(ob_arm, def)) { bPoseChannel *pchan = BKE_pose_channel_find_name(pose, def->name); float mat[4][4]; float world[4][4]; float inv_bind_mat[4][4]; // SL/OPEN_SIM COMPATIBILITY if (export_settings->open_sim) { // Only translations, no rotation vs armature float temp[4][4]; unit_m4(temp); copy_v3_v3(temp[3], pchan->bone->arm_mat[3]); mul_m4_m4m4(world, ob_arm->obmat, temp); // Add Maya restpose matrix (if defined as properties) float restpose_mat[4][4]; create_restpose_mat(pchan->bone, restpose_mat); mul_m4_m4m4(world, world, restpose_mat); } else { // make world-space matrix, arm_mat is armature-space mul_m4_m4m4(world, ob_arm->obmat, pchan->bone->arm_mat); } invert_m4_m4(mat, world); converter.mat4_to_dae(inv_bind_mat, mat); source.appendValues(inv_bind_mat); } } // back from rest positon if (!(flag & ARM_RESTPOS)) { arm->flag = flag; BKE_pose_where_is(scene, ob_arm); } source.finish(); return source_id; }
static void add_verts_to_dgroups(ReportList *reports, Scene *scene, Object *ob, Object *par, int heat, const bool mirror) { /* This functions implements the automatic computation of vertex group * weights, either through envelopes or using a heat equilibrium. * * This function can be called both when parenting a mesh to an armature, * or in weightpaint + posemode. In the latter case selection is taken * into account and vertex weights can be mirrored. * * The mesh vertex positions used are either the final deformed coords * from the derivedmesh in weightpaint mode, the final subsurf coords * when parenting, or simply the original mesh coords. */ bArmature *arm = par->data; Bone **bonelist, *bone; bDeformGroup **dgrouplist, **dgroupflip; bDeformGroup *dgroup; bPoseChannel *pchan; Mesh *mesh; Mat4 bbone_array[MAX_BBONE_SUBDIV], *bbone = NULL; float (*root)[3], (*tip)[3], (*verts)[3]; int *selected; int numbones, vertsfilled = 0, i, j, segments = 0; int wpmode = (ob->mode & OB_MODE_WEIGHT_PAINT); struct { Object *armob; void *list; int heat; } looper_data; looper_data.armob = par; looper_data.heat = heat; looper_data.list = NULL; /* count the number of skinnable bones */ numbones = bone_looper(ob, arm->bonebase.first, &looper_data, bone_skinnable_cb); if (numbones == 0) return; if (BKE_object_defgroup_data_create(ob->data) == NULL) return; /* create an array of pointer to bones that are skinnable * and fill it with all of the skinnable bones */ bonelist = MEM_callocN(numbones * sizeof(Bone *), "bonelist"); looper_data.list = bonelist; bone_looper(ob, arm->bonebase.first, &looper_data, bone_skinnable_cb); /* create an array of pointers to the deform groups that * correspond to the skinnable bones (creating them * as necessary. */ dgrouplist = MEM_callocN(numbones * sizeof(bDeformGroup *), "dgrouplist"); dgroupflip = MEM_callocN(numbones * sizeof(bDeformGroup *), "dgroupflip"); looper_data.list = dgrouplist; bone_looper(ob, arm->bonebase.first, &looper_data, dgroup_skinnable_cb); /* create an array of root and tip positions transformed into * global coords */ root = MEM_callocN(numbones * sizeof(float) * 3, "root"); tip = MEM_callocN(numbones * sizeof(float) * 3, "tip"); selected = MEM_callocN(numbones * sizeof(int), "selected"); for (j = 0; j < numbones; ++j) { bone = bonelist[j]; dgroup = dgrouplist[j]; /* handle bbone */ if (heat) { if (segments == 0) { segments = 1; bbone = NULL; if ((par->pose) && (pchan = BKE_pose_channel_find_name(par->pose, bone->name))) { if (bone->segments > 1) { segments = bone->segments; b_bone_spline_setup(pchan, 1, bbone_array); bbone = bbone_array; } } } segments--; } /* compute root and tip */ if (bbone) { mul_v3_m4v3(root[j], bone->arm_mat, bbone[segments].mat[3]); if ((segments + 1) < bone->segments) { mul_v3_m4v3(tip[j], bone->arm_mat, bbone[segments + 1].mat[3]); } else { copy_v3_v3(tip[j], bone->arm_tail); } } else { copy_v3_v3(root[j], bone->arm_head); copy_v3_v3(tip[j], bone->arm_tail); } mul_m4_v3(par->obmat, root[j]); mul_m4_v3(par->obmat, tip[j]); /* set selected */ if (wpmode) { if ((arm->layer & bone->layer) && (bone->flag & BONE_SELECTED)) selected[j] = 1; } else selected[j] = 1; /* find flipped group */ if (dgroup && mirror) { char name_flip[MAXBONENAME]; BKE_deform_flip_side_name(name_flip, dgroup->name, false); dgroupflip[j] = defgroup_find_name(ob, name_flip); } } /* create verts */ mesh = (Mesh *)ob->data; verts = MEM_callocN(mesh->totvert * sizeof(*verts), "closestboneverts"); if (wpmode) { /* if in weight paint mode, use final verts from derivedmesh */ DerivedMesh *dm = mesh_get_derived_final(scene, ob, CD_MASK_BAREMESH); if (dm->foreachMappedVert) { mesh_get_mapped_verts_coords(dm, verts, mesh->totvert); vertsfilled = 1; } dm->release(dm); } else if (modifiers_findByType(ob, eModifierType_Subsurf)) { /* is subsurf on? Lets use the verts on the limit surface then. * = same amount of vertices as mesh, but vertices moved to the * subsurfed position, like for 'optimal'. */ subsurf_calculate_limit_positions(mesh, verts); vertsfilled = 1; } /* transform verts to global space */ for (i = 0; i < mesh->totvert; i++) { if (!vertsfilled) copy_v3_v3(verts[i], mesh->mvert[i].co); mul_m4_v3(ob->obmat, verts[i]); } /* compute the weights based on gathered vertices and bones */ if (heat) { const char *error = NULL; heat_bone_weighting(ob, mesh, verts, numbones, dgrouplist, dgroupflip, root, tip, selected, &error); if (error) { BKE_report(reports, RPT_WARNING, error); } } else { envelope_bone_weighting(ob, mesh, verts, numbones, bonelist, dgrouplist, dgroupflip, root, tip, selected, mat4_to_scale(par->obmat)); } /* only generated in some cases but can call anyway */ ED_mesh_mirror_spatial_table(ob, NULL, NULL, NULL, 'e'); /* free the memory allocated */ MEM_freeN(bonelist); MEM_freeN(dgrouplist); MEM_freeN(dgroupflip); MEM_freeN(root); MEM_freeN(tip); MEM_freeN(selected); MEM_freeN(verts); }
static int dgroup_skinnable_cb(Object *ob, Bone *bone, void *datap) { /* Bones that are deforming * are regarded to be "skinnable" and are eligible for * auto-skinning. * * This function performs 2 functions: * * a) If the bone is skinnable, it creates * a vertex group for ob that has * the name of the skinnable bone * (if one doesn't exist already). * b) If the pointer data is non null, * it is treated like a handle to a * bDeformGroup pointer -- the * bDeformGroup pointer is set to point * to the deform group with the bone's * name, and the pointer the handle * points to is incremented to point to the * next member of an array of pointers * to bDeformGroups. This way we can loop using * this function to construct an array of * pointers to bDeformGroups, all with names * of skinnable bones. */ bDeformGroup ***hgroup, *defgroup = NULL; int a, segments; struct { Object *armob; void *list; int heat; } *data = datap; int wpmode = (ob->mode & OB_MODE_WEIGHT_PAINT); bArmature *arm = data->armob->data; if (!wpmode || !(bone->flag & BONE_HIDDEN_P)) { if (!(bone->flag & BONE_NO_DEFORM)) { if (data->heat && data->armob->pose && BKE_pose_channel_find_name(data->armob->pose, bone->name)) segments = bone->segments; else segments = 1; if (!wpmode || ((arm->layer & bone->layer) && (bone->flag & BONE_SELECTED))) { if (!(defgroup = defgroup_find_name(ob, bone->name))) { defgroup = BKE_object_defgroup_add_name(ob, bone->name); } else if (defgroup->flag & DG_LOCK_WEIGHT) { /* In case vgroup already exists and is locked, do not modify it here. See T43814. */ defgroup = NULL; } } if (data->list != NULL) { hgroup = (bDeformGroup ***) &data->list; for (a = 0; a < segments; a++) { **hgroup = defgroup; ++*hgroup; } } return segments; } } return 0; }
/** * Allocate a new pose on the heap, and copy the src pose and it's channels * into the new pose. *dst is set to the newly allocated structure, and assumed to be NULL. * * \param dst Should be freed already, makes entire duplicate. */ void BKE_pose_copy_data(bPose **dst, bPose *src, const bool copy_constraints) { bPose *outPose; bPoseChannel *pchan; ListBase listb; if (!src) { *dst = NULL; return; } outPose = MEM_callocN(sizeof(bPose), "pose"); BLI_duplicatelist(&outPose->chanbase, &src->chanbase); /* Rebuild ghash here too, so that name lookups below won't be too bad... * BUT this will have the penalty that the ghash will be built twice * if BKE_pose_rebuild() gets called after this... */ if (outPose->chanbase.first != outPose->chanbase.last) { outPose->chanhash = NULL; BKE_pose_channels_hash_make(outPose); } outPose->iksolver = src->iksolver; outPose->ikdata = NULL; outPose->ikparam = MEM_dupallocN(src->ikparam); outPose->avs = src->avs; for (pchan = outPose->chanbase.first; pchan; pchan = pchan->next) { if (pchan->custom) { id_us_plus(&pchan->custom->id); } /* warning, O(n2) here, if done without the hash, but these are rarely used features. */ if (pchan->custom_tx) { pchan->custom_tx = BKE_pose_channel_find_name(outPose, pchan->custom_tx->name); } if (pchan->bbone_prev) { pchan->bbone_prev = BKE_pose_channel_find_name(outPose, pchan->bbone_prev->name); } if (pchan->bbone_next) { pchan->bbone_next = BKE_pose_channel_find_name(outPose, pchan->bbone_next->name); } if (copy_constraints) { BKE_constraints_copy(&listb, &pchan->constraints, true); // BKE_constraints_copy NULLs listb pchan->constraints = listb; pchan->mpath = NULL; /* motion paths should not get copied yet... */ } if (pchan->prop) { pchan->prop = IDP_CopyProperty(pchan->prop); } } /* for now, duplicate Bone Groups too when doing this */ if (copy_constraints) { BLI_duplicatelist(&outPose->agroups, &src->agroups); } *dst = outPose; }