diff options
author | Ove Murberg Henriksen <sorayasilvermoon@hotmail.com> | 2012-05-23 14:56:06 +0400 |
---|---|---|
committer | Ove Murberg Henriksen <sorayasilvermoon@hotmail.com> | 2012-05-23 14:56:06 +0400 |
commit | 736daa9f046958195112a46df084525120bacec2 (patch) | |
tree | 5c6e5705479db19fdeedf0b20514284a32072034 /source/blender/editors/object | |
parent | c4c75c33d0dd3222285b6799da3656316776592a (diff) | |
parent | c0f59c44f8f4a15368335337adc7b9aafbe3fca6 (diff) |
svn merge ^/trunk/blender -r46844:HEAD
Diffstat (limited to 'source/blender/editors/object')
-rw-r--r-- | source/blender/editors/object/object_bake.c | 2 | ||||
-rw-r--r-- | source/blender/editors/object/object_intern.h | 4 | ||||
-rw-r--r-- | source/blender/editors/object/object_modifier.c | 415 | ||||
-rw-r--r-- | source/blender/editors/object/object_ops.c | 5 |
4 files changed, 423 insertions, 3 deletions
diff --git a/source/blender/editors/object/object_bake.c b/source/blender/editors/object/object_bake.c index b89562e772b..810fe244984 100644 --- a/source/blender/editors/object/object_bake.c +++ b/source/blender/editors/object/object_bake.c @@ -534,7 +534,7 @@ static void get_ccgdm_data(DerivedMesh *lodm, DerivedMesh *hidm, const int *orig int grid_index = origindex[face_index]; int loc_offs = face_index % (1 << (2 * lvl)); int cell_index = loc_offs % ((side - 1) * (side - 1)); - int cell_side = grid_size / (side - 1); + int cell_side = (grid_size - 1) / (side - 1); int row = cell_index / (side - 1); int col = cell_index % (side - 1); diff --git a/source/blender/editors/object/object_intern.h b/source/blender/editors/object/object_intern.h index 4d67a620939..6f3cca442f0 100644 --- a/source/blender/editors/object/object_intern.h +++ b/source/blender/editors/object/object_intern.h @@ -160,6 +160,10 @@ void OBJECT_OT_multires_external_pack(struct wmOperatorType *ot); void OBJECT_OT_meshdeform_bind(struct wmOperatorType *ot); void OBJECT_OT_explode_refresh(struct wmOperatorType *ot); 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 47748fbd53b..9e891353f35 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" @@ -85,6 +87,8 @@ #include "object_intern.h" +static void modifier_skin_customdata_ensure(struct Object *ob); + /******************************** API ****************************/ ModifierData *ED_object_modifier_add(ReportList *reports, Main *bmain, Scene *scene, Object *ob, const char *name, int type) @@ -157,6 +161,10 @@ ModifierData *ED_object_modifier_add(ReportList *reports, Main *bmain, Scene *sc /* ensure that grid paint mask layer is created */ ED_sculpt_mask_layers_ensure(ob, (MultiresModifierData *)new_md); } + else if (type == eModifierType_Skin) { + /* ensure skin-node customdata exists */ + modifier_skin_customdata_ensure(ob); + } } DAG_id_tag_update(&ob->id, OB_RECALC_DATA); @@ -1131,7 +1139,7 @@ static int multires_reshape_exec(bContext *C, wmOperator *op) return OPERATOR_CANCELLED; } - CTX_DATA_BEGIN (C, Object *, selob, selected_editable_objects) + CTX_DATA_BEGIN(C, Object *, selob, selected_editable_objects) { if (selob->type == OB_MESH && selob != ob) { secondob = selob; @@ -1327,6 +1335,409 @@ void OBJECT_OT_multires_base_apply(wmOperatorType *ot) } +/************************** skin modifier ***********************/ + +static void modifier_skin_customdata_ensure(Object *ob) +{ + Mesh *me = ob->data; + BMesh *bm = me->edit_btmesh ? me->edit_btmesh->bm : NULL; + MVertSkin *vs; + + if (bm && !CustomData_has_layer(&bm->vdata, CD_MVERT_SKIN)) { + BMVert *v; + BMIter iter; + + BM_data_layer_add(bm, &bm->vdata, CD_MVERT_SKIN); + + /* Mark an arbitrary vertex as root */ + BM_ITER_MESH (v, &iter, bm, BM_VERTS_OF_MESH) { + vs = CustomData_bmesh_get(&bm->vdata, v->head.data, + CD_MVERT_SKIN); + vs->flag |= MVERT_SKIN_ROOT; + break; + } + } + else if (!CustomData_has_layer(&me->vdata, CD_MVERT_SKIN)) { + vs = CustomData_add_layer(&me->vdata, + CD_MVERT_SKIN, + CD_DEFAULT, + NULL, + me->totvert); + + /* Mark an arbitrary vertex as root */ + vs->flag |= MVERT_SKIN_ROOT; + } +} + +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) && + edit_modifier_poll_generic(C, &RNA_SkinModifier, (1 << OB_MESH))); +} + +static void skin_root_clear(BMesh *bm, BMVert *bm_vert, GHash *visited) +{ + BMEdge *bm_edge; + BMIter bm_iter; + + BM_ITER_ELEM (bm_edge, &bm_iter, bm_vert, BM_EDGES_OF_VERT) { + BMVert *v2 = BM_edge_other_vert(bm_edge, bm_vert); + + if (!BLI_ghash_lookup(visited, v2)) { + MVertSkin *vs = CustomData_bmesh_get(&bm->vdata, + v2->head.data, + CD_MVERT_SKIN); + + /* clear vertex root flag and add to visited set */ + vs->flag &= ~MVERT_SKIN_ROOT; + BLI_ghash_insert(visited, v2, v2); + + skin_root_clear(bm, v2, visited); + } + } +} + +static int skin_root_mark_exec(bContext *C, wmOperator *UNUSED(op)) +{ + Object *ob = CTX_data_edit_object(C); + Mesh *me = ob->data; + BMesh *bm = me->edit_btmesh->bm; + BMVert *bm_vert; + BMIter bm_iter; + GHash *visited; + + visited = BLI_ghash_ptr_new("skin_root_mark_exec visited"); + + modifier_skin_customdata_ensure(ob); + + BM_ITER_MESH (bm_vert, &bm_iter, bm, BM_VERTS_OF_MESH) { + if (!BLI_ghash_lookup(visited, bm_vert) && + bm_vert->head.hflag & BM_ELEM_SELECT) + { + MVertSkin *vs = CustomData_bmesh_get(&bm->vdata, + bm_vert->head.data, + CD_MVERT_SKIN); + + /* mark vertex as root and add to visited set */ + vs->flag |= MVERT_SKIN_ROOT; + BLI_ghash_insert(visited, bm_vert, bm_vert); + + /* clear root flag from all connected vertices (recursively) */ + skin_root_clear(bm, bm_vert, visited); + } + } + + BLI_ghash_free(visited, NULL, NULL); + + DAG_id_tag_update(&ob->id, OB_RECALC_DATA); + WM_event_add_notifier(C, NC_OBJECT | ND_MODIFIER, ob); + + return OPERATOR_FINISHED; +} + +void OBJECT_OT_skin_root_mark(wmOperatorType *ot) +{ + ot->name = "Skin Root Mark"; + ot->description = "Mark selected vertices as roots"; + ot->idname = "OBJECT_OT_skin_root_mark"; + + ot->poll = skin_edit_poll; + ot->exec = skin_root_mark_exec; + + /* flags */ + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; +} + +typedef enum { + SKIN_LOOSE_MARK, + SKIN_LOOSE_CLEAR +} SkinLooseAction; + +static int skin_loose_mark_clear_exec(bContext *C, wmOperator *op) +{ + Object *ob = CTX_data_edit_object(C); + Mesh *me = ob->data; + BMesh *bm = me->edit_btmesh->bm; + BMVert *bm_vert; + BMIter bm_iter; + SkinLooseAction action = RNA_enum_get(op->ptr, "action"); + + BM_ITER_MESH (bm_vert, &bm_iter, bm, BM_VERTS_OF_MESH) { + if (bm_vert->head.hflag & BM_ELEM_SELECT) { + MVertSkin *vs = CustomData_bmesh_get(&bm->vdata, + bm_vert->head.data, + CD_MVERT_SKIN); + + + switch (action) { + case SKIN_LOOSE_MARK: + vs->flag |= MVERT_SKIN_LOOSE; + break; + case SKIN_LOOSE_CLEAR: + vs->flag &= ~MVERT_SKIN_LOOSE; + break; + } + } + } + + DAG_id_tag_update(&ob->id, OB_RECALC_DATA); + WM_event_add_notifier(C, NC_OBJECT | ND_MODIFIER, ob); + + return OPERATOR_FINISHED; +} + +void OBJECT_OT_skin_loose_mark_clear(wmOperatorType *ot) +{ + static EnumPropertyItem action_items[] = { + {SKIN_LOOSE_MARK, "MARK", 0, "Mark", "Mark selected vertices as loose"}, + {SKIN_LOOSE_CLEAR, "CLEAR", 0, "Clear", "Set selected vertices as not loose"}, + {0, NULL, 0, NULL, NULL} + }; + + ot->name = "Skin Mark/Clear Loose"; + ot->description = "Mark/clear selected vertices as loose"; + ot->idname = "OBJECT_OT_skin_loose_mark_clear"; + + ot->poll = skin_edit_poll; + ot->exec = skin_loose_mark_clear_exec; + + /* flags */ + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; + + RNA_def_enum(ot->srna, "action", action_items, SKIN_LOOSE_MARK, "Action", NULL); +} + +static int skin_radii_equalize_exec(bContext *C, wmOperator *UNUSED(op)) +{ + Object *ob = CTX_data_edit_object(C); + Mesh *me = ob->data; + BMesh *bm = me->edit_btmesh->bm; + BMVert *bm_vert; + BMIter bm_iter; + + BM_ITER_MESH (bm_vert, &bm_iter, bm, BM_VERTS_OF_MESH) { + if (bm_vert->head.hflag & BM_ELEM_SELECT) { + MVertSkin *vs = CustomData_bmesh_get(&bm->vdata, + bm_vert->head.data, + CD_MVERT_SKIN); + float avg = (vs->radius[0] + vs->radius[1]) * 0.5f; + + vs->radius[0] = vs->radius[1] = avg; + } + } + + DAG_id_tag_update(&ob->id, OB_RECALC_DATA); + WM_event_add_notifier(C, NC_OBJECT | ND_MODIFIER, ob); + + return OPERATOR_FINISHED; +} + +void OBJECT_OT_skin_radii_equalize(wmOperatorType *ot) +{ + ot->name = "Skin Radii Equalize"; + ot->description = "Make skin radii of selected vertices equal"; + ot->idname = "OBJECT_OT_skin_radii_equalize"; + + ot->poll = skin_edit_poll; + ot->exec = skin_radii_equalize_exec; + + /* flags */ + 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) @@ -1516,7 +1927,7 @@ static void oceanbake_free(void *customdata) /* called by oceanbake, only to check job 'stop' value */ static int oceanbake_breakjob(void *UNUSED(customdata)) { - //OceanBakeJob *ob= (OceanBakeJob *)customdata; + //OceanBakeJob *ob = (OceanBakeJob *)customdata; //return *(ob->stop); /* this is not nice yet, need to make the jobs list template better diff --git a/source/blender/editors/object/object_ops.c b/source/blender/editors/object/object_ops.c index afc493f66f9..0c50ab58487 100644 --- a/source/blender/editors/object/object_ops.c +++ b/source/blender/editors/object/object_ops.c @@ -139,6 +139,11 @@ void ED_operatortypes_object(void) WM_operatortype_append(OBJECT_OT_multires_base_apply); WM_operatortype_append(OBJECT_OT_multires_external_save); WM_operatortype_append(OBJECT_OT_multires_external_pack); + 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); |