[Bf-blender-cvs] SVN commit: /data/svn/bf-blender [46895] trunk/blender/source/blender: Add operator to extract armature and vertex groups from skin.

Nicholas Bishop nicholasbishop at gmail.com
Tue May 22 17:29:57 CEST 2012


Revision: 46895
          http://projects.blender.org/scm/viewvc.php?view=rev&root=bf-blender&revision=46895
Author:   nicholasbishop
Date:     2012-05-22 15:29:57 +0000 (Tue, 22 May 2012)
Log Message:
-----------
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

Modified Paths:
--------------
    trunk/blender/source/blender/blenkernel/BKE_object.h
    trunk/blender/source/blender/blenkernel/intern/customdata.c
    trunk/blender/source/blender/blenkernel/intern/object.c
    trunk/blender/source/blender/editors/object/object_intern.h
    trunk/blender/source/blender/editors/object/object_modifier.c
    trunk/blender/source/blender/editors/object/object_ops.c

Modified: trunk/blender/source/blender/blenkernel/BKE_object.h
===================================================================
--- trunk/blender/source/blender/blenkernel/BKE_object.h	2012-05-22 15:29:44 UTC (rev 46894)
+++ trunk/blender/source/blender/blenkernel/BKE_object.h	2012-05-22 15:29:57 UTC (rev 46895)
@@ -53,6 +53,7 @@
 void BKE_object_workob_clear(struct Object *workob);
 void BKE_object_workob_calc_parent(struct Scene *scene, struct Object *ob, struct Object *workob);
 
+void BKE_object_transform_copy(struct Object *ob_tar, const struct Object *ob_src);
 struct SoftBody *copy_softbody(struct SoftBody *sb);
 struct BulletSoftBody *copy_bulletsoftbody(struct BulletSoftBody *sb);
 void BKE_object_copy_particlesystems(struct Object *obn, struct Object *ob);

Modified: trunk/blender/source/blender/blenkernel/intern/customdata.c
===================================================================
--- trunk/blender/source/blender/blenkernel/intern/customdata.c	2012-05-22 15:29:44 UTC (rev 46894)
+++ trunk/blender/source/blender/blenkernel/intern/customdata.c	2012-05-22 15:29:57 UTC (rev 46895)
@@ -1168,7 +1168,7 @@
     CD_MASK_MLOOPUV | CD_MASK_MLOOPCOL | CD_MASK_MTEXPOLY | CD_MASK_PREVIEW_MLOOPCOL |
     CD_MASK_PROP_STR | CD_MASK_ORIGSPACE | CD_MASK_ORIGSPACE_MLOOP | CD_MASK_ORCO | CD_MASK_TANGENT |
     CD_MASK_PREVIEW_MCOL | CD_MASK_NORMAL | CD_MASK_SHAPEKEY | CD_MASK_RECAST |
-    CD_MASK_ORIGINDEX | CD_MASK_POLYINDEX;
+    CD_MASK_ORIGINDEX | CD_MASK_POLYINDEX | CD_MASK_MVERT_SKIN;
 const CustomDataMask CD_MASK_BMESH =
     CD_MASK_MLOOPUV | CD_MASK_MLOOPCOL | CD_MASK_MTEXPOLY |
     CD_MASK_MSTICKY | CD_MASK_MDEFORMVERT | CD_MASK_PROP_FLT | CD_MASK_PROP_INT |

Modified: trunk/blender/source/blender/blenkernel/intern/object.c
===================================================================
--- trunk/blender/source/blender/blenkernel/intern/object.c	2012-05-22 15:29:44 UTC (rev 46894)
+++ trunk/blender/source/blender/blenkernel/intern/object.c	2012-05-22 15:29:57 UTC (rev 46895)
@@ -1090,7 +1090,7 @@
 	return NULL;
 }
 
-static void copy_object_transform(Object *ob_tar, Object *ob_src)
+void BKE_object_transform_copy(Object *ob_tar, const Object *ob_src)
 {
 	copy_v3_v3(ob_tar->loc, ob_src->loc);
 	copy_v3_v3(ob_tar->rot, ob_src->rot);
@@ -1365,7 +1365,7 @@
 		BKE_object_apply_mat4(ob, ob->obmat, FALSE, TRUE);
 	}
 	else {
-		copy_object_transform(ob, target);
+		BKE_object_transform_copy(ob, target);
 		ob->parent = target->parent; /* libdata */
 		copy_m4_m4(ob->parentinv, target->parentinv);
 	}

Modified: trunk/blender/source/blender/editors/object/object_intern.h
===================================================================
--- trunk/blender/source/blender/editors/object/object_intern.h	2012-05-22 15:29:44 UTC (rev 46894)
+++ trunk/blender/source/blender/editors/object/object_intern.h	2012-05-22 15:29:57 UTC (rev 46895)
@@ -163,6 +163,7 @@
 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);

Modified: trunk/blender/source/blender/editors/object/object_modifier.c
===================================================================
--- trunk/blender/source/blender/editors/object/object_modifier.c	2012-05-22 15:29:44 UTC (rev 46894)
+++ trunk/blender/source/blender/editors/object/object_modifier.c	2012-05-22 15:29:57 UTC (rev 46895)
@@ -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 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,7 +1550,193 @@
 	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 *********************/
 
 static int meshdeform_poll(bContext *C)

Modified: trunk/blender/source/blender/editors/object/object_ops.c
===================================================================
--- trunk/blender/source/blender/editors/object/object_ops.c	2012-05-22 15:29:44 UTC (rev 46894)
+++ trunk/blender/source/blender/editors/object/object_ops.c	2012-05-22 15:29:57 UTC (rev 46895)
@@ -142,6 +142,8 @@
 	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);




More information about the Bf-blender-cvs mailing list