forked from bartvdbraak/blender
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
This commit is contained in:
parent
11309a19e2
commit
45265b326a
@ -53,6 +53,7 @@ struct MovieClip;
|
|||||||
void BKE_object_workob_clear(struct Object *workob);
|
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_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 SoftBody *copy_softbody(struct SoftBody *sb);
|
||||||
struct BulletSoftBody *copy_bulletsoftbody(struct BulletSoftBody *sb);
|
struct BulletSoftBody *copy_bulletsoftbody(struct BulletSoftBody *sb);
|
||||||
void BKE_object_copy_particlesystems(struct Object *obn, struct Object *ob);
|
void BKE_object_copy_particlesystems(struct Object *obn, struct Object *ob);
|
||||||
|
@ -1168,7 +1168,7 @@ const CustomDataMask CD_MASK_DERIVEDMESH =
|
|||||||
CD_MASK_MLOOPUV | CD_MASK_MLOOPCOL | CD_MASK_MTEXPOLY | CD_MASK_PREVIEW_MLOOPCOL |
|
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_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_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 =
|
const CustomDataMask CD_MASK_BMESH =
|
||||||
CD_MASK_MLOOPUV | CD_MASK_MLOOPCOL | CD_MASK_MTEXPOLY |
|
CD_MASK_MLOOPUV | CD_MASK_MLOOPCOL | CD_MASK_MTEXPOLY |
|
||||||
CD_MASK_MSTICKY | CD_MASK_MDEFORMVERT | CD_MASK_PROP_FLT | CD_MASK_PROP_INT |
|
CD_MASK_MSTICKY | CD_MASK_MDEFORMVERT | CD_MASK_PROP_FLT | CD_MASK_PROP_INT |
|
||||||
|
@ -1090,7 +1090,7 @@ Object *BKE_object_pose_armature_get(Object *ob)
|
|||||||
return NULL;
|
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->loc, ob_src->loc);
|
||||||
copy_v3_v3(ob_tar->rot, ob_src->rot);
|
copy_v3_v3(ob_tar->rot, ob_src->rot);
|
||||||
@ -1365,7 +1365,7 @@ void BKE_object_make_proxy(Object *ob, Object *target, Object *gob)
|
|||||||
BKE_object_apply_mat4(ob, ob->obmat, FALSE, TRUE);
|
BKE_object_apply_mat4(ob, ob->obmat, FALSE, TRUE);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
copy_object_transform(ob, target);
|
BKE_object_transform_copy(ob, target);
|
||||||
ob->parent = target->parent; /* libdata */
|
ob->parent = target->parent; /* libdata */
|
||||||
copy_m4_m4(ob->parentinv, target->parentinv);
|
copy_m4_m4(ob->parentinv, target->parentinv);
|
||||||
}
|
}
|
||||||
|
@ -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_root_mark(struct wmOperatorType *ot);
|
||||||
void OBJECT_OT_skin_loose_mark_clear(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_radii_equalize(struct wmOperatorType *ot);
|
||||||
|
void OBJECT_OT_skin_armature_create(struct wmOperatorType *ot);
|
||||||
|
|
||||||
/* object_constraint.c */
|
/* object_constraint.c */
|
||||||
void OBJECT_OT_constraint_add(struct wmOperatorType *ot);
|
void OBJECT_OT_constraint_add(struct wmOperatorType *ot);
|
||||||
|
@ -35,6 +35,7 @@
|
|||||||
#include "MEM_guardedalloc.h"
|
#include "MEM_guardedalloc.h"
|
||||||
|
|
||||||
#include "DNA_anim_types.h"
|
#include "DNA_anim_types.h"
|
||||||
|
#include "DNA_armature_types.h"
|
||||||
#include "DNA_curve_types.h"
|
#include "DNA_curve_types.h"
|
||||||
#include "DNA_key_types.h"
|
#include "DNA_key_types.h"
|
||||||
#include "DNA_mesh_types.h"
|
#include "DNA_mesh_types.h"
|
||||||
@ -42,6 +43,7 @@
|
|||||||
#include "DNA_object_force.h"
|
#include "DNA_object_force.h"
|
||||||
#include "DNA_scene_types.h"
|
#include "DNA_scene_types.h"
|
||||||
|
|
||||||
|
#include "BLI_bitmap.h"
|
||||||
#include "BLI_math.h"
|
#include "BLI_math.h"
|
||||||
#include "BLI_listbase.h"
|
#include "BLI_listbase.h"
|
||||||
#include "BLI_string.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)
|
static int skin_edit_poll(bContext *C)
|
||||||
{
|
{
|
||||||
return (CTX_data_edit_object(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;
|
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 *********************/
|
/************************ mdef bind operator *********************/
|
||||||
|
|
||||||
|
@ -142,6 +142,8 @@ void ED_operatortypes_object(void)
|
|||||||
WM_operatortype_append(OBJECT_OT_skin_root_mark);
|
WM_operatortype_append(OBJECT_OT_skin_root_mark);
|
||||||
WM_operatortype_append(OBJECT_OT_skin_loose_mark_clear);
|
WM_operatortype_append(OBJECT_OT_skin_loose_mark_clear);
|
||||||
WM_operatortype_append(OBJECT_OT_skin_radii_equalize);
|
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_meshdeform_bind);
|
||||||
WM_operatortype_append(OBJECT_OT_explode_refresh);
|
WM_operatortype_append(OBJECT_OT_explode_refresh);
|
||||||
WM_operatortype_append(OBJECT_OT_ocean_bake);
|
WM_operatortype_append(OBJECT_OT_ocean_bake);
|
||||||
|
Loading…
Reference in New Issue
Block a user