static void blend_pose_offset_bone(bActionStrip *strip, bPose *dst, bPose *src, float srcweight, short mode) { /* matching offset bones */ /* take dst offset, and put src on on that location */ if(strip->offs_bone[0]==0) return; /* are we also blending with matching bones? */ if(strip->prev && strip->start>=strip->prev->start) { bPoseChannel *dpchan= get_pose_channel(dst, strip->offs_bone); if(dpchan) { bPoseChannel *spchan= get_pose_channel(src, strip->offs_bone); if(spchan) { float vec[3]; /* dst->ctime has the internal strip->prev action time */ /* map this time to nla time */ float ctime= get_actionstrip_frame(strip, src->ctime, 1); if( ctime > strip->prev->end) { bActionChannel *achan; /* add src to dest, minus the position of src on strip->prev->end */ ctime= get_actionstrip_frame(strip, strip->prev->end, 0); achan= get_action_channel(strip->act, strip->offs_bone); if(achan && achan->ipo) { bPoseChannel pchan; /* Evaluates and sets the internal ipo value */ calc_ipo(achan->ipo, ctime); /* This call also sets the pchan flags */ execute_action_ipo(achan, &pchan); /* store offset that moves src to location of pchan */ sub_v3_v3v3(vec, dpchan->loc, pchan.loc); mul_mat3_m4_v3(dpchan->bone->arm_mat, vec); } } else { /* store offset that moves src to location of dst */ sub_v3_v3v3(vec, dpchan->loc, spchan->loc); mul_mat3_m4_v3(dpchan->bone->arm_mat, vec); } /* if blending, we only add with factor scrweight */ mul_v3_fl(vec, srcweight); add_v3_v3(dst->cyclic_offset, vec); } } } add_v3_v3(dst->cyclic_offset, src->cyclic_offset); }
PyObject* BL_ActionActuator::PyGetChannel(PyObject* value) { char *string= _PyUnicode_AsString(value); 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 */ } // get_pose_channel accounts for NULL pose, run on both incase one exists but // the channel doesnt if( !(pchan=get_pose_channel(m_userpose, string)) && !(pchan=get_pose_channel(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; /* 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] ); */ }
/* 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= get_pose_channel(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++; } } }
/* perform syncing updates for Action Groups */ static void animchan_sync_group (bAnimContext *UNUSED(ac), bAnimListElem *ale) { 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= get_pose_channel(ob->pose, agrp->name); /* if one matches, sync the selection status */ if (pchan) { if (pchan->bone->flag & BONE_SELECTED) agrp->flag |= AGRP_SELECTED; else agrp->flag &= ~AGRP_SELECTED; } } } }
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= get_pose_channel(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; }
void ArmatureExporter::add_bone_transform(Object *ob_arm, Bone *bone, COLLADASW::Node& node) { bPoseChannel *pchan = get_pose_channel(ob_arm->pose, bone->name); float mat[4][4]; if (bone->parent) { // get bone-space matrix from armature-space bPoseChannel *parchan = get_pose_channel(ob_arm->pose, bone->parent->name); float invpar[4][4]; invert_m4_m4(invpar, parchan->pose_mat); mult_m4_m4m4(mat, invpar, pchan->pose_mat); } else { copy_m4_m4(mat, pchan->pose_mat); // Why? Joint's localspace is still it's parent node //get world-space from armature-space //mult_m4_m4m4(mat, ob_arm->obmat, pchan->pose_mat); } // SECOND_LIFE_COMPATIBILITY if(export_settings->second_life) { // Remove rotations vs armature from transform // parent_rest_rot * mat * irest_rot float temp[4][4]; copy_m4_m4(temp, bone->arm_mat); temp[3][0] = temp[3][1] = temp[3][2] = 0.0f; invert_m4(temp); mult_m4_m4m4(mat, mat, temp); if(bone->parent) { copy_m4_m4(temp, bone->parent->arm_mat); temp[3][0] = temp[3][1] = temp[3][2] = 0.0f; mult_m4_m4m4(mat, temp, mat); } } TransformWriter::add_node_transform(node, mat,NULL ); }
std::string ArmatureExporter::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; COLLADASW::FloatSourceF source(mSW); source.setId(source_id); source.setArrayId(source_id + ARRAY_ID_SUFFIX); source.setAccessorCount(BLI_countlist(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; where_is_pose(scene, ob_arm); } for (bDeformGroup *def = (bDeformGroup*)defbase->first; def; def = def->next) { if (is_bone_defgroup(ob_arm, def)) { bPoseChannel *pchan = get_pose_channel(pose, def->name); float mat[4][4]; float world[4][4]; float inv_bind_mat[4][4]; // make world-space matrix, arm_mat is armature-space mul_m4_m4m4(world, pchan->bone->arm_mat, ob_arm->obmat); 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; where_is_pose(scene, ob_arm); } source.finish(); return source_id; }
/* 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= get_pose_channel(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 ArmatureExporter::add_bone_transform(Object *ob_arm, Bone *bone, COLLADASW::Node& node) { bPoseChannel *pchan = get_pose_channel(ob_arm->pose, bone->name); float mat[4][4]; if (bone->parent) { // get bone-space matrix from armature-space bPoseChannel *parchan = get_pose_channel(ob_arm->pose, bone->parent->name); float invpar[4][4]; invert_m4_m4(invpar, parchan->pose_mat); mul_m4_m4m4(mat, pchan->pose_mat, invpar); } else { // get world-space from armature-space mul_m4_m4m4(mat, pchan->pose_mat, ob_arm->obmat); } TransformWriter::add_node_transform(node, mat,NULL ); }
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 = get_pose_channel(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_frame_to_ctime(scene, *it); BKE_animsys_evaluate_animdata(scene , &ob_arm->id, ob_arm->adt, ctime, ADT_RECALC_ANIM); where_is_pose_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); }
/* 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= get_pose_channel(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); }
static int object_hook_reset_exec(bContext *C, wmOperator *op) { PointerRNA ptr= CTX_data_pointer_get_type(C, "modifier", &RNA_HookModifier); int num= RNA_enum_get(op->ptr, "modifier"); Object *ob=NULL; HookModifierData *hmd=NULL; if (ptr.data) { /* if modifier context is available, use that */ ob = ptr.id.data; hmd= ptr.data; } else { /* use the provided property */ ob = CTX_data_edit_object(C); hmd = (HookModifierData *)BLI_findlink(&ob->modifiers, num); } if (!ob || !hmd) { BKE_report(op->reports, RPT_ERROR, "Couldn't find hook modifier"); return OPERATOR_CANCELLED; } /* reset functionality */ if(hmd->object) { bPoseChannel *pchan= get_pose_channel(hmd->object->pose, hmd->subtarget); if(hmd->subtarget[0] && pchan) { float imat[4][4], mat[4][4]; /* calculate the world-space matrix for the pose-channel target first, then carry on as usual */ mul_m4_m4m4(mat, pchan->pose_mat, hmd->object->obmat); invert_m4_m4(imat, mat); mul_serie_m4(hmd->parentinv, imat, ob->obmat, NULL, NULL, NULL, NULL, NULL, NULL); } else { invert_m4_m4(hmd->object->imat, hmd->object->obmat); mul_serie_m4(hmd->parentinv, hmd->object->imat, ob->obmat, NULL, NULL, NULL, NULL, NULL, NULL); } } DAG_id_tag_update(&ob->id, OB_RECALC_DATA); WM_event_add_notifier(C, NC_OBJECT|ND_MODIFIER, ob); return OPERATOR_FINISHED; }
/* dont 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) { where_is_object(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= get_pose_channel(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]); } }
/* both poses should be in sync */ void copy_pose_result(bPose *to, bPose *from) { bPoseChannel *pchanto, *pchanfrom; if(to==NULL || from==NULL) { printf("pose result copy error to:%p from:%p\n", (void *)to, (void *)from); // debug temp return; } if (to==from) { printf("copy_pose_result source and target are the same\n"); return; } for(pchanfrom= from->chanbase.first; pchanfrom; pchanfrom= pchanfrom->next) { pchanto= get_pose_channel(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 */ VECCOPY(pchanto->loc, pchanfrom->loc); QUATCOPY(pchanto->quat, pchanfrom->quat); VECCOPY(pchanto->eul, pchanfrom->eul); VECCOPY(pchanto->size, pchanfrom->size); VECCOPY(pchanto->pose_head, pchanfrom->pose_head); VECCOPY(pchanto->pose_tail, pchanfrom->pose_tail); pchanto->rotmode= pchanfrom->rotmode; pchanto->flag= pchanfrom->flag; pchanto->protectflag= pchanfrom->protectflag; } } }
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 = get_pose_channel(ob_arm->pose, bone->name); if (!pchan) return; find_frames(ob_arm, fra); if (flag & ARM_RESTPOS) { arm->flag &= ~ARM_RESTPOS; where_is_pose(scene, ob_arm); } if (fra.size()) { dae_baked_animation(fra ,ob_arm, bone ); } if (flag & ARM_RESTPOS) arm->flag = flag; where_is_pose(scene, ob_arm); }
/* perform syncing updates for F-Curves */ static void animchan_sync_fcurve (bAnimContext *UNUSED(ac), bAnimListElem *ale) { FCurve *fcu= (FCurve *)ale->data; ID *owner_id= ale->id; /* major priority is selection status, so refer to the checks done in anim_filter.c * skip_fcurve_selected_data() for reference about what's going on here... */ if (ELEM3(NULL, fcu, fcu->rna_path, owner_id)) return; if (GS(owner_id->name) == ID_OB) { Object *ob= (Object *)owner_id; /* only affect if F-Curve involves pose.bones */ if ((fcu->rna_path) && strstr(fcu->rna_path, "pose.bones")) { bPoseChannel *pchan; char *bone_name; /* get bone-name, and check if this bone is selected */ bone_name= BLI_getQuotedStr(fcu->rna_path, "pose.bones["); pchan= get_pose_channel(ob->pose, bone_name); if (bone_name) MEM_freeN(bone_name); /* F-Curve selection depends on whether the bone is selected */ if ((pchan) && (pchan->bone)) { if (pchan->bone->flag & BONE_SELECTED) fcu->flag |= FCURVE_SELECTED; else fcu->flag &= ~FCURVE_SELECTED; } } } else if (GS(owner_id->name) == ID_SCE) { Scene *scene = (Scene *)owner_id; /* only affect if F-Curve involves sequence_editor.sequences */ if ((fcu->rna_path) && strstr(fcu->rna_path, "sequences_all")) { Editing *ed= seq_give_editing(scene, FALSE); Sequence *seq; char *seq_name; /* get strip name, and check if this strip is selected */ seq_name= BLI_getQuotedStr(fcu->rna_path, "sequences_all["); seq = get_seq_by_name(ed->seqbasep, seq_name, FALSE); if (seq_name) MEM_freeN(seq_name); /* can only add this F-Curve if it is selected */ if (seq) { if (seq->flag & SELECT) fcu->flag |= FCURVE_SELECTED; else fcu->flag &= ~FCURVE_SELECTED; } } } else if (GS(owner_id->name) == ID_NT) { bNodeTree *ntree = (bNodeTree *)owner_id; /* check for selected nodes */ if ((fcu->rna_path) && strstr(fcu->rna_path, "nodes")) { bNode *node; char *node_name; /* get strip name, and check if this strip is selected */ node_name= BLI_getQuotedStr(fcu->rna_path, "nodes["); node = nodeFindNodebyName(ntree, node_name); if (node_name) MEM_freeN(node_name); /* can only add this F-Curve if it is selected */ if (node) { if (node->flag & NODE_SELECT) fcu->flag |= FCURVE_SELECTED; else fcu->flag &= ~FCURVE_SELECTED; } } } }
static void deformVerts(ModifierData *md, Object *ob, DerivedMesh *dm, float (*vertexCos)[3], int numVerts, int UNUSED(useRenderParams), int UNUSED(isFinalCalc)) { HookModifierData *hmd = (HookModifierData*) md; bPoseChannel *pchan= get_pose_channel(hmd->object->pose, hmd->subtarget); float vec[3], mat[4][4], dmat[4][4]; int i, *index_pt; const float falloff_squared= hmd->falloff * hmd->falloff; /* for faster comparisons */ int max_dvert= 0; MDeformVert *dvert= NULL; int defgrp_index = -1; /* get world-space matrix of target, corrected for the space the verts are in */ if (hmd->subtarget[0] && pchan) { /* bone target if there's a matching pose-channel */ mul_m4_m4m4(dmat, pchan->pose_mat, hmd->object->obmat); } else { /* just object target */ copy_m4_m4(dmat, hmd->object->obmat); } invert_m4_m4(ob->imat, ob->obmat); mul_serie_m4(mat, ob->imat, dmat, hmd->parentinv, NULL, NULL, NULL, NULL, NULL); if((defgrp_index= defgroup_name_index(ob, hmd->name)) != -1) { Mesh *me = ob->data; if(dm) { dvert= dm->getVertDataArray(dm, CD_MDEFORMVERT); if(dvert) { max_dvert = numVerts; } } else if(me->dvert) { dvert= me->dvert; if(dvert) { max_dvert = me->totvert; } } } /* Regarding index range checking below. * * This should always be true and I don't generally like * "paranoid" style code like this, but old files can have * indices that are out of range because old blender did * not correct them on exit editmode. - zr */ if(hmd->force == 0.0f) { /* do nothing, avoid annoying checks in the loop */ } else if(hmd->indexar) { /* vertex indices? */ const float fac_orig= hmd->force; float fac; const int *origindex_ar; /* if DerivedMesh is present and has original index data, * use it */ if(dm && (origindex_ar= dm->getVertDataArray(dm, CD_ORIGINDEX))) { for(i= 0, index_pt= hmd->indexar; i < hmd->totindex; i++, index_pt++) { if(*index_pt < numVerts) { int j; for(j = 0; j < numVerts; j++) { if(origindex_ar[j] == *index_pt) { float *co = vertexCos[j]; if((fac= hook_falloff(hmd->cent, co, falloff_squared, fac_orig))) { if(dvert) fac *= defvert_find_weight(dvert+j, defgrp_index); if(fac) { mul_v3_m4v3(vec, mat, co); interp_v3_v3v3(co, co, vec, fac); } } } } } } } else { /* missing dm or ORIGINDEX */ for(i= 0, index_pt= hmd->indexar; i < hmd->totindex; i++, index_pt++) { if(*index_pt < numVerts) { float *co = vertexCos[*index_pt]; if((fac= hook_falloff(hmd->cent, co, falloff_squared, fac_orig))) { if(dvert) fac *= defvert_find_weight(dvert+(*index_pt), defgrp_index); if(fac) { mul_v3_m4v3(vec, mat, co); interp_v3_v3v3(co, co, vec, fac); } } } } } } else if(dvert) { /* vertex group hook */ int i; const float fac_orig= hmd->force; for(i = 0; i < max_dvert; i++, dvert++) { float fac; float *co = vertexCos[i]; if((fac= hook_falloff(hmd->cent, co, falloff_squared, fac_orig))) { fac *= defvert_find_weight(dvert, defgrp_index); if(fac) { mul_v3_m4v3(vec, mat, co); interp_v3_v3v3(co, co, vec, fac); } } } } }
Bone *ArmatureExporter::get_bone_from_defgroup(Object *ob_arm, bDeformGroup* def) { bPoseChannel *pchan = get_pose_channel(ob_arm->pose, def->name); return pchan ? pchan->bone : NULL; }
bPoseChannel *SkinInfo::get_pose_channel_from_node(COLLADAFW::Node *node) { return get_pose_channel(ob_arm->pose, bc_get_joint_name(node)); }
/* checks validity of object pointers, and NULLs, * if Bone doesnt exist it sets the CONSTRAINT_DISABLE flag */ static void test_constraints (Object *owner, const char substring[]) { bConstraint *curcon; ListBase *conlist= NULL; int type; if (owner==NULL) return; /* Check parents */ if (strlen(substring)) { switch (owner->type) { case OB_ARMATURE: type = CONSTRAINT_OBTYPE_BONE; break; default: type = CONSTRAINT_OBTYPE_OBJECT; break; } } else type = CONSTRAINT_OBTYPE_OBJECT; /* Get the constraint list for this object */ switch (type) { case CONSTRAINT_OBTYPE_OBJECT: conlist = &owner->constraints; break; case CONSTRAINT_OBTYPE_BONE: { Bone *bone; bPoseChannel *chan; bone = get_named_bone( ((bArmature *)owner->data), substring ); chan = get_pose_channel(owner->pose, substring); if (bone && chan) { conlist = &chan->constraints; } } break; } /* Check all constraints - is constraint valid? */ if (conlist) { for (curcon = conlist->first; curcon; curcon=curcon->next) { bConstraintTypeInfo *cti= constraint_get_typeinfo(curcon); ListBase targets = {NULL, NULL}; bConstraintTarget *ct; /* clear disabled-flag first */ curcon->flag &= ~CONSTRAINT_DISABLE; if (curcon->type == CONSTRAINT_TYPE_KINEMATIC) { bKinematicConstraint *data = curcon->data; /* bad: we need a separate set of checks here as poletarget is * optional... otherwise poletarget must exist too or else * the constraint is deemed invalid */ /* default IK check ... */ if (exist_object(data->tar) == 0) { data->tar = NULL; curcon->flag |= CONSTRAINT_DISABLE; } else if (data->tar == owner) { if (!get_named_bone(get_armature(owner), data->subtarget)) { curcon->flag |= CONSTRAINT_DISABLE; } } if (data->poletar) { if (exist_object(data->poletar) == 0) { data->poletar = NULL; curcon->flag |= CONSTRAINT_DISABLE; } else if (data->poletar == owner) { if (!get_named_bone(get_armature(owner), data->polesubtarget)) { curcon->flag |= CONSTRAINT_DISABLE; } } } /* ... can be overwritten here */ BIK_test_constraint(owner, curcon); /* targets have already been checked for this */ continue; } else if (curcon->type == CONSTRAINT_TYPE_ACTION) { bActionConstraint *data = curcon->data; /* validate action */ if (data->act == NULL) curcon->flag |= CONSTRAINT_DISABLE; } else if (curcon->type == CONSTRAINT_TYPE_FOLLOWPATH) { bFollowPathConstraint *data = curcon->data; /* don't allow track/up axes to be the same */ if (data->upflag==data->trackflag) curcon->flag |= CONSTRAINT_DISABLE; if (data->upflag+3==data->trackflag) curcon->flag |= CONSTRAINT_DISABLE; } else if (curcon->type == CONSTRAINT_TYPE_TRACKTO) { bTrackToConstraint *data = curcon->data; /* don't allow track/up axes to be the same */ if (data->reserved2==data->reserved1) curcon->flag |= CONSTRAINT_DISABLE; if (data->reserved2+3==data->reserved1) curcon->flag |= CONSTRAINT_DISABLE; } else if (curcon->type == CONSTRAINT_TYPE_LOCKTRACK) { bLockTrackConstraint *data = curcon->data; if (data->lockflag==data->trackflag) curcon->flag |= CONSTRAINT_DISABLE; if (data->lockflag+3==data->trackflag) curcon->flag |= CONSTRAINT_DISABLE; } /* Check targets for constraints */ if (cti && cti->get_constraint_targets) { cti->get_constraint_targets(curcon, &targets); /* disable and clear constraints targets that are incorrect */ for (ct= targets.first; ct; ct= ct->next) { /* general validity checks (for those constraints that need this) */ if (exist_object(ct->tar) == 0) { ct->tar = NULL; curcon->flag |= CONSTRAINT_DISABLE; } else if (ct->tar == owner) { if (!get_named_bone(get_armature(owner), ct->subtarget)) { curcon->flag |= CONSTRAINT_DISABLE; } } /* target checks for specific constraints */ if (ELEM(curcon->type, CONSTRAINT_TYPE_FOLLOWPATH, CONSTRAINT_TYPE_CLAMPTO)) { if (ct->tar) { if (ct->tar->type != OB_CURVE) { ct->tar= NULL; curcon->flag |= CONSTRAINT_DISABLE; } else { Curve *cu= ct->tar->data; /* auto-set 'Path' setting on curve so this works */ cu->flag |= CU_PATH; } } } } /* free any temporary targets */ if (cti->flush_constraint_targets) cti->flush_constraint_targets(curcon, &targets, 0); } } } }
std::string AnimationExporter::create_4x4_source(std::vector<float> &frames , Object * ob_arm, Bone *bone , const std::string& anim_id) { COLLADASW::InputSemantic::Semantics semantic = COLLADASW::InputSemantic::OUTPUT; std::string source_id = anim_id + get_semantic_suffix(semantic); COLLADASW::Float4x4Source source(mSW); source.setId(source_id); source.setArrayId(source_id + ARRAY_ID_SUFFIX); source.setAccessorCount(frames.size()); source.setAccessorStride(16); COLLADASW::SourceBase::ParameterNameList ¶m = source.getParameterNameList(); add_source_parameters(param, semantic, false, NULL, true); source.prepareToAppendValues(); bPoseChannel *parchan = NULL; bPoseChannel *pchan = NULL; bPose *pose = ob_arm->pose; pchan = get_pose_channel(pose, bone->name); if (!pchan) return ""; parchan = pchan->parent; enable_fcurves(ob_arm->adt->action, bone->name); std::vector<float>::iterator it; int j = 0; for (it = frames.begin(); it != frames.end(); it++) { float mat[4][4], ipar[4][4]; float ctime = BKE_frame_to_ctime(scene, *it); BKE_animsys_evaluate_animdata(scene , &ob_arm->id, ob_arm->adt, ctime, ADT_RECALC_ANIM); where_is_pose_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); UnitConverter converter; float outmat[4][4]; converter.mat4_to_dae(outmat,mat); source.appendValues(outmat); j++; } enable_fcurves(ob_arm->adt->action, NULL); source.finish(); return source_id; }
static DerivedMesh *applyModifier(ModifierData *md, Object *ob, DerivedMesh *derivedData, int UNUSED(useRenderParams), int UNUSED(isFinalCalc)) { 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 --- */ GHash *vgroupHash; 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, mmd->ob_arm, mmd->ob_arm->pose, ob->defbase.first)) return derivedData; bone_select_array= MEM_mallocN(defbase_tot * sizeof(char), "mask array"); for (i = 0, def = ob->defbase.first; def; def = def->next, i++) { pchan = get_pose_channel(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; } } /* hashes for finding mapping of: * - vgroups to indices -> vgroupHash (string, int) * - bones to vgroup indices -> boneHash (index of vgroup, dummy) */ vgroupHash= BLI_ghash_new(BLI_ghashutil_strhash, BLI_ghashutil_strcmp, "mask vgroup gh"); /* build mapping of names of vertex groups to indices */ for (i = 0, def = ob->defbase.first; def; def = def->next, i++) BLI_ghash_insert(vgroupHash, def->name, SET_INT_IN_POINTER(i)); /* if no bones selected, free hashes and return original mesh */ if (bone_select_tot == 0) { BLI_ghash_free(vgroupHash, NULL, NULL); MEM_freeN(bone_select_array); return derivedData; } /* repeat the previous check, but for dverts */ dvert= dm->getVertDataArray(dm, CD_MDEFORMVERT); if (dvert == NULL) { BLI_ghash_free(vgroupHash, NULL, NULL); MEM_freeN(bone_select_array); return derivedData; } /* hashes for quickly providing a mapping from old to new - use key=oldindex, value=newindex */ vertHash= BLI_ghash_new(BLI_ghashutil_inthash, BLI_ghashutil_intcmp, "mask vert gh"); /* add vertices which exist in vertexgroups into vertHash for filtering */ for (i= 0, dv= dvert; i < maxVerts; i++, dv++) { MDeformWeight *dw= dv->dw; int j; for (j= dv->totweight; j > 0; j--, dw++) { if (dw->def_nr < defbase_tot) { if (bone_select_array[dw->def_nr]) { if (dw->weight != 0.0f) { 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 (dw) continue; } else { /* if this vert isn't in the vgroup, don't include it in vertHash */ if (!dw) 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 */ BLI_ghash_free(vgroupHash, NULL, NULL); MEM_freeN(bone_select_array); } else /* --- Using Nominated VertexGroup only --- */ { int defgrp_index = defgroup_name_index(ob, mmd->vgroup); /* get dverts */ if (defgrp_index >= 0) dvert = dm->getVertDataArray(dm, CD_MDEFORMVERT); /* if no vgroup (i.e. dverts) found, return the initial mesh */ if ((defgrp_index < 0) || (dvert == NULL)) return dm; /* hashes for quickly providing a mapping from old to new - use key=oldindex, value=newindex */ vertHash= BLI_ghash_new(BLI_ghashutil_inthash, BLI_ghashutil_intcmp, "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_new(BLI_ghashutil_inthash, BLI_ghashutil_intcmp, "mask ed2 gh"); polyHash= BLI_ghash_new(BLI_ghashutil_inthash, BLI_ghashutil_intcmp, "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; }
void AnimationExporter::sample_and_write_bone_animation(Object *ob_arm, Bone *bone, int transform_type) { bArmature *arm = (bArmature*)ob_arm->data; int flag = arm->flag; std::vector<float> fra; char prefix[256]; BLI_snprintf(prefix, sizeof(prefix), "pose.bones[\"%s\"]", bone->name); bPoseChannel *pchan = get_pose_channel(ob_arm->pose, bone->name); if (!pchan) return; //Fill frame array with key frame values framed at @param:transform_type switch (transform_type) { case 0: find_rotation_frames(ob_arm, fra, prefix, pchan->rotmode); break; case 1: find_frames(ob_arm, fra, prefix, "scale"); break; case 2: find_frames(ob_arm, fra, prefix, "location"); break; default: return; } // exit rest position if (flag & ARM_RESTPOS) { arm->flag &= ~ARM_RESTPOS; where_is_pose(scene, ob_arm); } //v array will hold all values which will be exported. if (fra.size()) { float *values = (float*)MEM_callocN(sizeof(float) * 3 * fra.size(), "temp. anim frames"); sample_animation(values, fra, transform_type, bone, ob_arm, pchan); if (transform_type == 0) { // write x, y, z curves separately if it is rotation float *axisValues = (float*)MEM_callocN(sizeof(float) * fra.size(), "temp. anim frames"); for (int i = 0; i < 3; i++) { for (unsigned int j = 0; j < fra.size(); j++) axisValues[j] = values[j * 3 + i]; dae_bone_animation(fra, axisValues, transform_type, i, id_name(ob_arm), bone->name); } MEM_freeN(axisValues); } else { // write xyz at once if it is location or scale dae_bone_animation(fra, values, transform_type, -1, id_name(ob_arm), bone->name); } MEM_freeN(values); } // restore restpos if (flag & ARM_RESTPOS) arm->flag = flag; where_is_pose(scene, ob_arm); }