/* use this when the loc/size/rot of the parent has changed but the children * should stay in the same place, e.g. for apply-size-rot or object center */ static void ignore_parent_tx(Main *bmain, Scene *scene, Object *ob) { Object workob; Object *ob_child; /* a change was made, adjust the children to compensate */ for (ob_child = bmain->object.first; ob_child; ob_child = ob_child->id.next) { if (ob_child->parent == ob) { BKE_object_apply_mat4(ob_child, ob_child->obmat, TRUE, FALSE); BKE_object_workob_calc_parent(scene, ob_child, &workob); invert_m4_m4(ob_child->parentinv, workob.obmat); } } }
/* helper for apply_armature_pose2bones - fixes parenting of objects that are bone-parented to armature */ static void applyarmature_fix_boneparents(Scene *scene, Object *armob) { Object workob, *ob; /* go through all objects in database */ for (ob = G.main->object.first; ob; ob = ob->id.next) { /* if parent is bone in this armature, apply corrections */ if ((ob->parent == armob) && (ob->partype == PARBONE)) { /* apply current transform from parent (not yet destroyed), * then calculate new parent inverse matrix */ BKE_object_apply_mat4(ob, ob->obmat, false, false); BKE_object_workob_calc_parent(scene, ob, &workob); invert_m4_m4(ob->parentinv, workob.obmat); } } }
// a shortened version of parent_set_exec() // if is_parent_space is true then ob->obmat will be multiplied by par->obmat before parenting int bc_set_parent(Object *ob, Object *par, bContext *C, bool is_parent_space) { Object workob; Scene *sce = CTX_data_scene(C); if (!par || bc_test_parent_loop(par, ob)) return false; ob->parent = par; ob->partype = PAROBJECT; ob->parsubstr[0] = 0; if (is_parent_space) { float mat[4][4]; // calc par->obmat BKE_object_where_is_calc(sce, par); // move child obmat into world space mul_m4_m4m4(mat, par->obmat, ob->obmat); copy_m4_m4(ob->obmat, mat); } // apply child obmat (i.e. decompose it into rot/loc/size) BKE_object_apply_mat4(ob, ob->obmat, 0, 0); // compute parentinv BKE_object_workob_calc_parent(sce, ob, &workob); invert_m4_m4(ob->parentinv, workob.obmat); DAG_id_tag_update(&ob->id, OB_RECALC_OB | OB_RECALC_DATA); DAG_id_tag_update(&par->id, OB_RECALC_OB); /** done once after import */ #if 0 DAG_relations_tag_update(bmain); WM_event_add_notifier(C, NC_OBJECT | ND_TRANSFORM, NULL); #endif return true; }
void SkinInfo::link_armature(bContext *C, Object *ob, std::map<COLLADAFW::UniqueId, COLLADAFW::Node *>& joint_by_uid, TransformReader *tm) { Main *bmain = CTX_data_main(C); Scene *scene = CTX_data_scene(C); ModifierData *md = ED_object_modifier_add(NULL, bmain, scene, ob, NULL, eModifierType_Armature); ArmatureModifierData *amd = (ArmatureModifierData *)md; amd->object = ob_arm; copy_m4_m4(ob->obmat, bind_shape_matrix); BKE_object_apply_mat4(ob, ob->obmat, 0, 0); #if 1 bc_set_parent(ob, ob_arm, C); #else Object workob; ob->parent = ob_arm; ob->partype = PAROBJECT; BKE_object_workob_calc_parent(scene, ob, &workob); invert_m4_m4(ob->parentinv, workob.obmat); ob->recalc |= OB_RECALC_OB | OB_RECALC_DATA; DAG_scene_sort(bmain, scene); DAG_ids_flush_update(bmain, 0); WM_event_add_notifier(C, NC_OBJECT | ND_TRANSFORM, NULL); #endif amd->deformflag = ARM_DEF_VGROUP; // create all vertex groups std::vector<JointData>::iterator it; int joint_index; for (it = joint_data.begin(), joint_index = 0; it != joint_data.end(); it++, joint_index++) { const char *name = "Group"; // skip joints that have invalid UID if ((*it).joint_uid == COLLADAFW::UniqueId::INVALID) continue; // name group by joint node name if (joint_by_uid.find((*it).joint_uid) != joint_by_uid.end()) { name = bc_get_joint_name(joint_by_uid[(*it).joint_uid]); } ED_vgroup_add_name(ob, (char *)name); } // <vcount> - number of joints per vertex - joints_per_vertex // <v> - [[bone index, weight index] * joints per vertex] * vertices - weight indices // ^ bone index can be -1 meaning weight toward bind shape, how to express this in Blender? // for each vertex in weight indices // for each bone index in vertex // add vertex to group at group index // treat group index -1 specially // get def group by index with BLI_findlink for (unsigned int vertex = 0, weight = 0; vertex < joints_per_vertex.getCount(); vertex++) { unsigned int limit = weight + joints_per_vertex[vertex]; for (; weight < limit; weight++) { int joint = joint_indices[weight], joint_weight = weight_indices[weight]; // -1 means "weight towards the bind shape", we just don't assign it to any group if (joint != -1) { bDeformGroup *def = (bDeformGroup *)BLI_findlink(&ob->defbase, joint); ED_vgroup_vert_add(ob, def, vertex, weights[joint_weight], WEIGHT_REPLACE); } } } }