Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNicholas Bishop <nicholasbishop@gmail.com>2012-05-22 19:29:57 +0400
committerNicholas Bishop <nicholasbishop@gmail.com>2012-05-22 19:29:57 +0400
commit45265b326a2854a59327c3d171a3f4797944cc79 (patch)
tree2ecfd8b7b88de63bd0b4332b8d7fae130e0ce7b1 /source/blender/editors
parent11309a19e2cdeaeed3a2462b1bcb4138084cd7bf (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')
-rw-r--r--source/blender/editors/object/object_intern.h1
-rw-r--r--source/blender/editors/object/object_modifier.c194
-rw-r--r--source/blender/editors/object/object_ops.c2
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);