diff options
author | Nicholas Bishop <nicholasbishop@gmail.com> | 2012-05-22 19:29:57 +0400 |
---|---|---|
committer | Nicholas Bishop <nicholasbishop@gmail.com> | 2012-05-22 19:29:57 +0400 |
commit | 45265b326a2854a59327c3d171a3f4797944cc79 (patch) | |
tree | 2ecfd8b7b88de63bd0b4332b8d7fae130e0ce7b1 /source/blender/editors/object | |
parent | 11309a19e2cdeaeed3a2462b1bcb4138084cd7bf (diff) |
Add operator to extract armature and vertex groups from skin.
* The operator creates bones for each input edge (does not subdivide
them like the skin operator does), adds a fake root bone for skin
roots with multiple children.
* The operator adds vertex weight groups to the original mesh.
* Make copy_object_transform() public, used to match the armature
object to the mesh object.
Skin modifier documentation:
http://wiki.blender.org/index.php/User:Nicholasbishop/SkinModifier
Diffstat (limited to 'source/blender/editors/object')
-rw-r--r-- | source/blender/editors/object/object_intern.h | 1 | ||||
-rw-r--r-- | source/blender/editors/object/object_modifier.c | 194 | ||||
-rw-r--r-- | source/blender/editors/object/object_ops.c | 2 |
3 files changed, 197 insertions, 0 deletions
diff --git a/source/blender/editors/object/object_intern.h b/source/blender/editors/object/object_intern.h index 2bd53a3c0a7..4b33c5663ba 100644 --- a/source/blender/editors/object/object_intern.h +++ b/source/blender/editors/object/object_intern.h @@ -163,6 +163,7 @@ void OBJECT_OT_ocean_bake(struct wmOperatorType *ot); void OBJECT_OT_skin_root_mark(struct wmOperatorType *ot); void OBJECT_OT_skin_loose_mark_clear(struct wmOperatorType *ot); void OBJECT_OT_skin_radii_equalize(struct wmOperatorType *ot); +void OBJECT_OT_skin_armature_create(struct wmOperatorType *ot); /* object_constraint.c */ void OBJECT_OT_constraint_add(struct wmOperatorType *ot); diff --git a/source/blender/editors/object/object_modifier.c b/source/blender/editors/object/object_modifier.c index e98ff4a6984..e13e15e2a69 100644 --- a/source/blender/editors/object/object_modifier.c +++ b/source/blender/editors/object/object_modifier.c @@ -35,6 +35,7 @@ #include "MEM_guardedalloc.h" #include "DNA_anim_types.h" +#include "DNA_armature_types.h" #include "DNA_curve_types.h" #include "DNA_key_types.h" #include "DNA_mesh_types.h" @@ -42,6 +43,7 @@ #include "DNA_object_force.h" #include "DNA_scene_types.h" +#include "BLI_bitmap.h" #include "BLI_math.h" #include "BLI_listbase.h" #include "BLI_string.h" @@ -1367,6 +1369,12 @@ static void modifier_skin_customdata_ensure(Object *ob) } } +static int skin_poll(bContext *C) +{ + return (!CTX_data_edit_object(C) && + edit_modifier_poll_generic(C, &RNA_SkinModifier, (1<<OB_MESH))); +} + static int skin_edit_poll(bContext *C) { return (CTX_data_edit_object(C) && @@ -1542,6 +1550,192 @@ void OBJECT_OT_skin_radii_equalize(wmOperatorType *ot) ot->flag = OPTYPE_REGISTER|OPTYPE_UNDO; } +static void skin_armature_bone_create(Object *skin_ob, + MVert *mvert, MEdge *medge, + bArmature *arm, + BLI_bitmap edges_visited, + const MeshElemMap *emap, + EditBone *parent_bone, + int parent_v) +{ + int i; + + for(i = 0; i < emap[parent_v].count; i++) { + int endx = emap[parent_v].indices[i]; + const MEdge *e = &medge[endx]; + EditBone *bone; + bDeformGroup *dg; + int v; + + /* ignore edge if already visited */ + if(BLI_BITMAP_GET(edges_visited, endx)) + continue; + BLI_BITMAP_SET(edges_visited, endx); + + v = (e->v1 == parent_v ? e->v2 : e->v1); + + bone = MEM_callocN(sizeof(EditBone), + "skin_armature_bone_create EditBone"); + + bone->parent = parent_bone; + bone->layer = 1; + bone->flag |= BONE_CONNECTED; + + copy_v3_v3(bone->head, mvert[parent_v].co); + copy_v3_v3(bone->tail, mvert[v].co); + bone->rad_head = bone->rad_tail = 0.25; + BLI_snprintf(bone->name, sizeof(bone->name), "Bone.%.2d", endx); + + BLI_addtail(arm->edbo, bone); + + /* add bDeformGroup */ + if((dg = ED_vgroup_add_name(skin_ob, bone->name))) { + ED_vgroup_vert_add(skin_ob, dg, parent_v, 1, WEIGHT_REPLACE); + ED_vgroup_vert_add(skin_ob, dg, v, 1, WEIGHT_REPLACE); + } + + skin_armature_bone_create(skin_ob, + mvert, medge, + arm, + edges_visited, + emap, + bone, + v); + } +} + +static Object *modifier_skin_armature_create(struct Scene *scene, + Object *skin_ob) +{ + BLI_bitmap edges_visited; + DerivedMesh *deform_dm; + MVert *mvert; + Mesh *me = skin_ob->data; + Object *arm_ob; + bArmature *arm; + MVertSkin *mvert_skin; + MeshElemMap *emap; + int *emap_mem; + int v; + + deform_dm = mesh_get_derived_deform(scene, skin_ob, CD_MASK_BAREMESH); + mvert = deform_dm->getVertArray(deform_dm); + + /* add vertex weights to original mesh */ + CustomData_add_layer(&me->vdata, + CD_MDEFORMVERT, + CD_CALLOC, + NULL, + me->totvert); + + arm_ob = BKE_object_add(scene, OB_ARMATURE); + BKE_object_transform_copy(arm_ob, skin_ob); + arm = arm_ob->data; + arm->layer = 1; + arm_ob->dtx |= OB_DRAWXRAY; + arm->drawtype = ARM_LINE; + arm->edbo = MEM_callocN(sizeof(ListBase), "edbo armature"); + + mvert_skin = CustomData_get_layer(&me->vdata, CD_MVERT_SKIN); + create_vert_edge_map(&emap, &emap_mem, + me->medge, me->totvert, me->totedge); + + edges_visited = BLI_BITMAP_NEW(me->totedge, "edge_visited"); + + /* note: we use EditBones here, easier to set them up and use + * edit-armature functions to convert back to regular bones */ + for(v = 0; v < me->totvert; v++) { + if(mvert_skin[v].flag & MVERT_SKIN_ROOT) { + EditBone *bone = NULL; + + /* Unless the skin root has just one adjacent edge, create + a fake root bone (have it going off in the Y direction + (arbitrary) */ + if (emap[v].count > 1) { + bone = MEM_callocN(sizeof(EditBone), "EditBone"); + + copy_v3_v3(bone->head, me->mvert[v].co); + copy_v3_v3(bone->tail, me->mvert[v].co); + bone->layer = 1; + + bone->head[1] = 1.0f; + bone->rad_head = bone->rad_tail = 0.25; + + BLI_addtail(arm->edbo, bone); + } + + if(emap[v].count >= 1) { + skin_armature_bone_create(skin_ob, + mvert, me->medge, + arm, + edges_visited, + emap, + bone, + v); + } + } + } + + MEM_freeN(edges_visited); + MEM_freeN(emap); + MEM_freeN(emap_mem); + + ED_armature_from_edit(arm_ob); + ED_armature_edit_free(arm_ob); + + return arm_ob; +} + +static int skin_armature_create_exec(bContext *C, wmOperator *op) +{ + Main *bmain = CTX_data_main(C); + Scene *scene = CTX_data_scene(C); + Object *ob = CTX_data_active_object(C), *arm_ob; + ModifierData *skin_md; + ArmatureModifierData *arm_md; + + /* create new armature */ + arm_ob = modifier_skin_armature_create(scene, ob); + + /* add a modifier to connect the new armature to the mesh */ + arm_md= (ArmatureModifierData*)modifier_new(eModifierType_Armature); + if (arm_md) { + skin_md = edit_modifier_property_get(op, ob, eModifierType_Skin); + BLI_insertlinkafter(&ob->modifiers, skin_md, arm_md); + + arm_md->object = arm_ob; + arm_md->deformflag = ARM_DEF_VGROUP | ARM_DEF_QUATERNION; + DAG_scene_sort(bmain, scene); + DAG_id_tag_update(&ob->id, OB_RECALC_DATA); + } + + WM_event_add_notifier(C, NC_OBJECT|ND_MODIFIER, ob); + + return OPERATOR_FINISHED; +} + +static int skin_armature_create_invoke(bContext *C, wmOperator *op, wmEvent *UNUSED(event)) +{ + if (edit_modifier_invoke_properties(C, op)) + return skin_armature_create_exec(C, op); + else + return OPERATOR_CANCELLED; +} + +void OBJECT_OT_skin_armature_create(wmOperatorType *ot) +{ + ot->name = "Skin Armature Create"; + ot->description = "Create an armature that parallels the skin layout"; + ot->idname = "OBJECT_OT_skin_armature_create"; + + ot->poll = skin_poll; + ot->invoke = skin_armature_create_invoke; + ot->exec = skin_armature_create_exec; + + /* flags */ + ot->flag = OPTYPE_REGISTER|OPTYPE_UNDO; + edit_modifier_properties(ot); +} /************************ mdef bind operator *********************/ diff --git a/source/blender/editors/object/object_ops.c b/source/blender/editors/object/object_ops.c index 1f09d8fd5e4..01f6b641709 100644 --- a/source/blender/editors/object/object_ops.c +++ b/source/blender/editors/object/object_ops.c @@ -142,6 +142,8 @@ void ED_operatortypes_object(void) WM_operatortype_append(OBJECT_OT_skin_root_mark); WM_operatortype_append(OBJECT_OT_skin_loose_mark_clear); WM_operatortype_append(OBJECT_OT_skin_radii_equalize); + WM_operatortype_append(OBJECT_OT_skin_armature_create); + WM_operatortype_append(OBJECT_OT_meshdeform_bind); WM_operatortype_append(OBJECT_OT_explode_refresh); WM_operatortype_append(OBJECT_OT_ocean_bake); |