finished bmeshafying merge, though probably needs further testing and debugging. also fixed nasty bug in DM_to_mesh.

This commit is contained in:
2009-08-31 23:07:05 +00:00
parent 4c849249bc
commit c91e8e6ca1
6 changed files with 319 additions and 165 deletions

View File

@@ -406,6 +406,8 @@ void DM_to_mesh(DerivedMesh *dm, Mesh *me)
totloop += iter->len;
}
iter->free(iter);
tmp.totloop = totloop;
CustomData_copy(&dm->vertData, &tmp.vdata, CD_MASK_MESH, CD_DUPLICATE, totvert);
CustomData_copy(&dm->edgeData, &tmp.edata, CD_MASK_MESH, CD_DUPLICATE, totedge);

View File

@@ -237,6 +237,35 @@ BMOpDefine def_collapse = {
};
/*
Facedata point Merge
Merge uv/vcols at a specific vertex.
*/
BMOpDefine def_pointmerge_facedata = {
"pointmerge_facedata",
{{BMOP_OPSLOT_ELEMENT_BUF, "verts"}, /*input vertices*/
{BMOP_OPSLOT_ELEMENT_BUF, "snapv"}, /*snap vertex*/
{0, /*null-terminating sentinel*/}},
bmesh_pointmerge_facedata_exec,
0,
};
/*
Average Vertices Facevert Data
Merge uv/vcols associated with the input vertices at
the bounding box center. (I know, it's not averaging but
the vert_snap_to_bb_center is just too long).
*/
BMOpDefine def_vert_average_facedata = {
"vert_average_facedata",
{{BMOP_OPSLOT_ELEMENT_BUF, "verts"}, /*input vertices*/
{0, /*null-terminating sentinel*/}},
bmesh_vert_average_facedata_exec,
0,
};
/*
Point Merge
@@ -704,6 +733,8 @@ BMOpDefine *opdefines[] = {
&def_similarfaces,
&def_similaredges,
&def_similarverts,
&def_pointmerge_facedata,
&def_vert_average_facedata,
};
int bmesh_total_ops = (sizeof(opdefines) / sizeof(void*));

View File

@@ -49,4 +49,7 @@ void bmesh_collapse_exec(BMesh *bm, BMOperator *op);
void bmesh_similarfaces_exec(BMesh *bm, BMOperator *op);
void bmesh_similaredges_exec(BMesh *bm, BMOperator *op);
void bmesh_similarverts_exec(BMesh *bm, BMOperator *op);
void bmesh_pointmerge_facedata_exec(BMesh *bm, BMOperator *op);
void bmesh_vert_average_facedata_exec(BMesh *bm, BMOperator *op);
#endif

View File

@@ -213,17 +213,120 @@ static int vergaverco(const void *e1, const void *e2)
#define EDGE_MARK 1
void bmesh_pointmerge_facedata_exec(BMesh *bm, BMOperator *op)
{
BMOIter siter;
BMIter iter;
BMVert *v, *snapv;
BMLoop *l, *firstl = NULL;
float fac;
int i, tot;
snapv = BMO_IterNew(&siter, bm, op, "snapv", BM_VERT);
tot = BM_Vert_FaceCount(snapv);
if (!tot)
return;
fac = 1.0f / tot;
BM_ITER(l, &iter, bm, BM_LOOPS_OF_VERT, snapv) {
if (!firstl) {
firstl = l;
}
for (i=0; i<bm->ldata.totlayer; i++) {
if (CustomData_layer_has_math(&bm->ldata, i)) {
int type = bm->ldata.layers[i].type;
void *e1, *e2;
e1 = CustomData_bmesh_get_layer_n(&bm->ldata, firstl->head.data, i);
e2 = CustomData_bmesh_get_layer_n(&bm->ldata, l->head.data, i);
CustomData_data_multiply(type, e2, fac);
if (l != firstl)
CustomData_data_add(type, e1, e2);
}
}
}
BMO_ITER(v, &siter, bm, op, "verts", BM_VERT) {
BM_ITER(l, &iter, bm, BM_LOOPS_OF_VERT, v) {
if (l == firstl)
continue;
CustomData_bmesh_copy_data(&bm->ldata, &bm->ldata, firstl->head.data, &l->head.data);
}
}
}
void bmesh_vert_average_facedata_exec(BMesh *bm, BMOperator *op)
{
BMOIter siter;
BMIter iter;
BMVert *v;
BMLoop *l, *firstl = NULL;
CDBlockBytes min, max;
void *block;
int i, type;
for (i=0; i<bm->ldata.totlayer; i++) {
if (!CustomData_layer_has_math(&bm->ldata, i))
continue;
type = bm->ldata.layers[i].type;
CustomData_data_initminmax(type, &min, &max);
BMO_ITER(v, &siter, bm, op, "verts", BM_VERT) {
BM_ITER(l, &iter, bm, BM_LOOPS_OF_VERT, v) {
block = CustomData_bmesh_get_layer_n(&bm->ldata, l->head.data, i);
CustomData_data_dominmax(type, block, &min, &max);
}
}
CustomData_data_multiply(type, &min, 0.5f);
CustomData_data_multiply(type, &max, 0.5f);
CustomData_data_add(type, &min, &max);
BMO_ITER(v, &siter, bm, op, "verts", BM_VERT) {
BM_ITER(l, &iter, bm, BM_LOOPS_OF_VERT, v) {
block = CustomData_bmesh_get_layer_n(&bm->ldata, l->head.data, i);
CustomData_data_copy_value(type, &min, block);
}
}
}
}
void bmesh_pointmerge_exec(BMesh *bm, BMOperator *op)
{
BMOperator weldop;
BMOIter siter;
BMVert *v, *snapv = NULL;
float vec[3];
BMO_Get_Vec(op, "mergeco", vec);
//BMO_CallOpf(bm, "collapse_uvs edges=%s", op, "edges");
BMO_Init_Op(&weldop, "weldverts");
BMO_ITER(v, &siter, bm, op, "verts", BM_VERT) {
if (!snapv) {
snapv = v;
VECCOPY(snapv->co, vec);
} else {
BMO_Insert_MapPointer(bm, &weldop, "targetmap", v, snapv);
}
}
BMO_Exec_Op(bm, &weldop);
BMO_Finish_Op(bm, &weldop);
}
void bmesh_collapse_exec(BMesh *bm, BMOperator *op)
{
BMOperator weldop;
BMWalker walker;
BMOIter siter;
BMIter iter, liter, liter2;
BMVert *v;
BMIter iter;
BMEdge *e, **edges = NULL;
V_DECLARE(edges);
float min[3], max[3];
@@ -276,11 +379,9 @@ void bmesh_collapse_exec(BMesh *bm, BMOperator *op)
/*uv collapse function*/
void bmesh_collapsecon_do_layer(BMesh *bm, BMOperator *op, int layer)
{
BMIter iter, liter, liter2;
BMIter iter, liter;
BMFace *f;
BMLoop *l, *l2;
BMEdge *e;
BMVert *v;
BMWalker walker;
void **blocks = NULL;
V_DECLARE(blocks);

View File

@@ -1632,7 +1632,6 @@ static int edge_rotate_selected(bContext *C, wmOperator *op)
Object *obedit= CTX_data_edit_object(C);
BMEditMesh *em= ((Mesh *)obedit->data)->edit_btmesh;
BMOperator bmop;
BMOIter siter;
BMEdge *eed;
BMIter iter;
int ccw = RNA_int_get(op->ptr, "direction") == 1; // direction == 2 when clockwise and ==1 for counter CW.
@@ -2423,3 +2422,179 @@ void MESH_OT_colors_mirror(wmOperatorType *ot)
/* props */
RNA_def_enum(ot->srna, "axis", axis_items, DIRECTION_CW, "Axis", "Axis to mirror colors around.");
}
static int merge_firstlast(BMEditMesh *em, int first, int uvmerge, wmOperator *wmop)
{
BMVert *mergevert;
BMEditSelection *ese;
/* do sanity check in mergemenu in edit.c ?*/
if(first == 0){
ese = em->bm->selected.last;
mergevert= (BMVert*)ese->data;
}
else{
ese = em->bm->selected.first;
mergevert = (BMVert*)ese->data;
}
if (!BM_TestHFlag(mergevert, BM_SELECT))
return OPERATOR_CANCELLED;
if (uvmerge) {
if (!EDBM_CallOpf(em, wmop, "pointmerge_facedata verts=%hv snapv=%e", BM_SELECT, mergevert))
return OPERATOR_CANCELLED;
}
if (!EDBM_CallOpf(em, wmop, "pointmerge verts=%hv mergeco=%v", BM_SELECT, mergevert->co))
return OPERATOR_CANCELLED;
return OPERATOR_FINISHED;
}
static int merge_target(BMEditMesh *em, Scene *scene, View3D *v3d,
int target, int uvmerge, wmOperator *wmop)
{
BMIter iter;
BMVert *v;
float *co, cent[3] = {0.0f, 0.0f, 0.0f}, fac;
int i;
if (target) {
co = give_cursor(scene, v3d);
} else {
i = 0;
BM_ITER(v, &iter, em->bm, BM_VERTS_OF_MESH, NULL) {
if (!BM_TestHFlag(v, BM_SELECT))
continue;
VECADD(cent, cent, v->co);
i++;
}
if (!i)
return OPERATOR_CANCELLED;
fac = 1.0f / (float)i;
VECMUL(cent, fac);
co = cent;
}
if (!co)
return OPERATOR_CANCELLED;
if (uvmerge) {
if (!EDBM_CallOpf(em, wmop, "vert_average_facedata verts=%hv", BM_SELECT))
return OPERATOR_CANCELLED;
}
if (!EDBM_CallOpf(em, wmop, "pointmerge verts=%hv mergeco=%v", BM_SELECT, co))
return OPERATOR_CANCELLED;
return OPERATOR_FINISHED;
}
static int merge_exec(bContext *C, wmOperator *op)
{
Scene *scene= CTX_data_scene(C);
View3D *v3d = CTX_wm_view3d(C);
Object *obedit= CTX_data_edit_object(C);
BMEditMesh *em= ((Mesh *)obedit->data)->edit_btmesh;
int status= 0, uvs= RNA_boolean_get(op->ptr, "uvs");
switch(RNA_enum_get(op->ptr, "type")) {
case 3:
status = merge_target(em, scene, v3d, 0, uvs, op);
break;
case 4:
status = merge_target(em, scene, v3d, 1, uvs, op);
break;
case 1:
status = merge_firstlast(em, 0, uvs, op);
break;
case 6:
status = merge_firstlast(em, 1, uvs, op);
break;
case 5:
status = 1;
if (!EDBM_CallOpf(em, op, "collapse edges=%he", BM_SELECT))
status = 0;
break;
}
if(!status)
return OPERATOR_CANCELLED;
DAG_object_flush_update(scene, obedit, OB_RECALC_DATA);
WM_event_add_notifier(C, NC_OBJECT|ND_GEOM_SELECT, obedit);
return OPERATOR_FINISHED;
}
static EnumPropertyItem merge_type_items[]= {
{6, "FIRST", 0, "At First", ""},
{1, "LAST", 0, "At Last", ""},
{3, "CENTER", 0, "At Center", ""},
{4, "CURSOR", 0, "At Cursor", ""},
{5, "COLLAPSE", 0, "Collapse", ""},
{0, NULL, 0, NULL, NULL}};
static EnumPropertyItem *merge_type_itemf(bContext *C, PointerRNA *ptr, int *free)
{
Object *obedit;
EnumPropertyItem *item= NULL;
int totitem= 0;
if(!C) /* needed for docs */
return merge_type_items;
obedit= CTX_data_edit_object(C);
if(obedit && obedit->type == OB_MESH) {
BMEditMesh *em= ((Mesh*)obedit->data)->edit_btmesh;
if(em->selectmode & SCE_SELECT_VERTEX) {
if(em->bm->selected.first && em->bm->selected.last &&
((BMEditSelection*)em->bm->selected.first)->type == BM_VERT && ((BMEditSelection*)em->bm->selected.last)->type == BM_VERT) {
RNA_enum_items_add_value(&item, &totitem, merge_type_items, 6);
RNA_enum_items_add_value(&item, &totitem, merge_type_items, 1);
}
else if(em->bm->selected.first && ((BMEditSelection*)em->bm->selected.first)->type == BM_VERT)
RNA_enum_items_add_value(&item, &totitem, merge_type_items, 1);
else if(em->bm->selected.last && ((BMEditSelection*)em->bm->selected.last)->type == BM_VERT)
RNA_enum_items_add_value(&item, &totitem, merge_type_items, 6);
}
RNA_enum_items_add_value(&item, &totitem, merge_type_items, 3);
RNA_enum_items_add_value(&item, &totitem, merge_type_items, 4);
RNA_enum_items_add_value(&item, &totitem, merge_type_items, 5);
RNA_enum_item_end(&item, &totitem);
*free= 1;
return item;
}
return NULL;
}
void MESH_OT_merge(wmOperatorType *ot)
{
PropertyRNA *prop;
/* identifiers */
ot->name= "Merge";
ot->idname= "MESH_OT_merge";
/* api callbacks */
ot->exec= merge_exec;
ot->invoke= WM_menu_invoke;
ot->poll= ED_operator_editmesh;
/* flags */
ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
/* properties */
prop= RNA_def_enum(ot->srna, "type", merge_type_items, 3, "Type", "Merge method to use.");
RNA_def_enum_funcs(prop, merge_type_itemf);
RNA_def_boolean(ot->srna, "uvs", 0, "UVs", "Move UVs according to merge.");
}

View File

@@ -5417,164 +5417,6 @@ int collapseEdges(EditMesh *em)
return mergecount;
}
int merge_firstlast(EditMesh *em, int first, int uvmerge)
{
EditVert *eve,*mergevert;
EditSelection *ese;
/* do sanity check in mergemenu in edit.c ?*/
if(first == 0){
ese = em->selected.last;
mergevert= (EditVert*)ese->data;
}
else{
ese = em->selected.first;
mergevert = (EditVert*)ese->data;
}
if(mergevert->f&SELECT){
for (eve=em->verts.first; eve; eve=eve->next){
if (eve->f&SELECT)
VECCOPY(eve->co,mergevert->co);
}
}
if(uvmerge && CustomData_has_layer(&em->fdata, CD_MTFACE)){
for(eve=em->verts.first; eve; eve=eve->next) eve->f1 = 0;
for(eve=em->verts.first; eve; eve=eve->next){
if(eve->f&SELECT) eve->f1 = 1;
}
collapseuvs(em, mergevert);
}
return removedoublesflag(em, 1, 0, MERGELIMIT);
}
int merge_target(EditMesh *em, int target, int uvmerge)
{
EditVert *eve;
// XXX not working
if(target) snap_sel_to_curs();
else snap_to_center();
if(uvmerge && CustomData_has_layer(&em->fdata, CD_MTFACE)){
for(eve=em->verts.first; eve; eve=eve->next) eve->f1 = 0;
for(eve=em->verts.first; eve; eve=eve->next){
if(eve->f&SELECT) eve->f1 = 1;
}
collapseuvs(em, NULL);
}
return removedoublesflag(em, 1, 0, MERGELIMIT);
}
#undef MERGELIMIT
static int merge_exec(bContext *C, wmOperator *op)
{
Scene *scene= CTX_data_scene(C);
Object *obedit= CTX_data_edit_object(C);
EditMesh *em= BKE_mesh_get_editmesh((Mesh *)obedit->data);
int count= 0, uvs= RNA_boolean_get(op->ptr, "uvs");
switch(RNA_enum_get(op->ptr, "type")) {
case 3:
count = merge_target(em, 0, uvs);
break;
case 4:
count = merge_target(em, 1, uvs);
break;
case 1:
count = merge_firstlast(em, 0, uvs);
break;
case 6:
count = merge_firstlast(em, 1, uvs);
break;
case 2:
count = collapseEdges(em);
break;
}
if(!count)
return OPERATOR_CANCELLED;
BKE_mesh_end_editmesh(obedit->data, em);
DAG_object_flush_update(scene, obedit, OB_RECALC_DATA);
WM_event_add_notifier(C, NC_OBJECT|ND_GEOM_SELECT, obedit);
return OPERATOR_FINISHED;
}
static EnumPropertyItem merge_type_items[]= {
{6, "FIRST", 0, "At First", ""},
{1, "LAST", 0, "At Last", ""},
{3, "CENTER", 0, "At Center", ""},
{4, "CURSOR", 0, "At Cursor", ""},
{5, "COLLAPSE", 0, "Collapse", ""},
{0, NULL, 0, NULL, NULL}};
static EnumPropertyItem *merge_type_itemf(bContext *C, PointerRNA *ptr, int *free)
{
Object *obedit;
EnumPropertyItem *item= NULL;
int totitem= 0;
if(!C) /* needed for docs */
return merge_type_items;
obedit= CTX_data_edit_object(C);
if(obedit && obedit->type == OB_MESH) {
EditMesh *em= BKE_mesh_get_editmesh(obedit->data);
if(em->selectmode & SCE_SELECT_VERTEX) {
if(em->selected.first && em->selected.last &&
((EditSelection*)em->selected.first)->type == EDITVERT && ((EditSelection*)em->selected.last)->type == EDITVERT) {
RNA_enum_items_add_value(&item, &totitem, merge_type_items, 6);
RNA_enum_items_add_value(&item, &totitem, merge_type_items, 1);
}
else if(em->selected.first && ((EditSelection*)em->selected.first)->type == EDITVERT)
RNA_enum_items_add_value(&item, &totitem, merge_type_items, 1);
else if(em->selected.last && ((EditSelection*)em->selected.last)->type == EDITVERT)
RNA_enum_items_add_value(&item, &totitem, merge_type_items, 6);
}
RNA_enum_items_add_value(&item, &totitem, merge_type_items, 3);
RNA_enum_items_add_value(&item, &totitem, merge_type_items, 4);
RNA_enum_items_add_value(&item, &totitem, merge_type_items, 5);
RNA_enum_item_end(&item, &totitem);
*free= 1;
return item;
}
return NULL;
}
void MESH_OT_merge(wmOperatorType *ot)
{
PropertyRNA *prop;
/* identifiers */
ot->name= "Merge";
ot->idname= "MESH_OT_merge";
/* api callbacks */
ot->exec= merge_exec;
ot->invoke= WM_menu_invoke;
ot->poll= ED_operator_editmesh;
/* flags */
ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
/* properties */
prop= RNA_def_enum(ot->srna, "type", merge_type_items, 3, "Type", "Merge method to use.");
RNA_def_enum_funcs(prop, merge_type_itemf);
RNA_def_boolean(ot->srna, "uvs", 0, "UVs", "Move UVs according to merge.");
}
/************************ Vertex Path Operator *************************/
typedef struct PathNode {