diff options
author | Joseph Eagar <joeedh@gmail.com> | 2009-02-12 19:59:51 +0300 |
---|---|---|
committer | Joseph Eagar <joeedh@gmail.com> | 2009-02-12 19:59:51 +0300 |
commit | 01a12fa553f40a23c45241b788af983f03f156bf (patch) | |
tree | 984b0ecf44a3f754fe3bc3f8c1a761e53adee0e0 /source/blender/editors/mesh/editmesh_lib.c | |
parent | 47b8684d0f9060a65ce3b5b337f5ad25d082f277 (diff) |
Replaced unified extrude edges/faces code (the stuff specificaly for
edges/faces,extrudeflag_edgess, not the entire extrude system) with
a bmesh version. This stress-tested the operator api, and I had to
code some new stuff,including:
* An api to iterate over Mapping slots and array slots. It's modeled
after the normal iterator api.
* The ability to copy mapping slots.
* More mapping functions.
* In addition to being able to flag elements in a buffer,
you can now unflag them (much clearer then passing in ~flag
I think).
The extrude edge/faces code has multiple layers. At the top
level is a funtion in editmesh_lib.c, which takes care of selection,
handles mirror modifiers, etc. It calls the extrude operator, which
in turns calls split, which calls dupe/del. Note that split needed
a slot to exclude things from being deleting (e.g. when extruding
a single isolated face).
The basic idea (reflected in original design of split/dupe/del by Briggs)
is to use the split function to do the heavy work of extrude. split spits
out new geometry and mappings from boundary edges, for extrude (it should
also spit out other mappings, but that's for later).
Briggs: you may want to look over this, hopefully I didn't do anything
too evil.
I probably should spend some time going over the 2.5 mesh operators and
cleaning them up, splitting ones that need splitting, etc, and in general
getting them to work properly.
Diffstat (limited to 'source/blender/editors/mesh/editmesh_lib.c')
-rw-r--r-- | source/blender/editors/mesh/editmesh_lib.c | 120 |
1 files changed, 119 insertions, 1 deletions
diff --git a/source/blender/editors/mesh/editmesh_lib.c b/source/blender/editors/mesh/editmesh_lib.c index 0ee4d2f8274..61bfa51e06b 100644 --- a/source/blender/editors/mesh/editmesh_lib.c +++ b/source/blender/editors/mesh/editmesh_lib.c @@ -58,6 +58,7 @@ editmesh_lib: generic (no UI, no menus) operations/evaluators for editmesh data #include "ED_view3d.h" #include "mesh_intern.h" +#include "bmesh.h" /* ****************** stats *************** */ @@ -1135,10 +1136,127 @@ short extrudeflag_verts_indiv(EditMesh *em, short flag, float *nor) return 'g'; // g is grab } +short BM_extrude_edgeflag(Object *obedit, BMesh *bm, int eflag, float *nor) +{ + BMIter iter; + BMOIter siter; + BMOperator extop; + BMEdge *edge; + BMFace *f; + void *el; + ModifierData *md; + int flag; + + switch (eflag) { + case SELECT: + flag = BM_SELECT; + break; + default: + flag = BM_SELECT; + break; + } + + for (f=BMIter_New(&iter, bm, BM_FACES, NULL);f;f=BMIter_Step(&iter)) { + add_normal_aligned(nor, f->no); + } + Normalize(nor); + + BMO_Init_Op(&extop, BMOP_EXTRUDE_EDGECONTEXT); + BMO_HeaderFlag_To_Slot(bm, &extop, BMOP_EXFACE_EDGEFACEIN, + flag, BM_EDGE|BM_FACE); + + for (edge=BMIter_New(&iter, bm, BM_EDGES, NULL); edge; edge=BMIter_Step(&iter)) { + BM_Select_Edge(bm, edge, 0); + } + + for (f=BMIter_New(&iter, bm, BM_FACES, NULL); f; f=BMIter_Step(&iter)) { + BM_Select_Face(bm, f, 0); + } + + /* If a mirror modifier with clipping is on, we need to adjust some + * of the cases above to handle edges on the line of symmetry. + */ + for (; md; md=md->next) { + if (md->type==eModifierType_Mirror) { + MirrorModifierData *mmd = (MirrorModifierData*) md; + + if(mmd->flag & MOD_MIR_CLIPPING) { + float mtx[4][4]; + if (mmd->mirror_ob) { + float imtx[4][4]; + Mat4Invert(imtx, mmd->mirror_ob->obmat); + Mat4MulMat4(mtx, obedit->obmat, imtx); + } + + for (edge=BMIter_New(&iter,bm,BM_EDGES,NULL); + edge; edge=BMIter_Step(&iter)) + { + if(edge->head.flag & flag) { + float co1[3], co2[3]; + + VecCopyf(co1, edge->v1->co); + VecCopyf(co2, edge->v2->co); + + if (mmd->mirror_ob) { + VecMat4MulVecfl(co1, mtx, co1); + VecMat4MulVecfl(co2, mtx, co2); + } + + if (mmd->flag & MOD_MIR_AXIS_X) + if ( (fabs(co1[0]) < mmd->tolerance) && + (fabs(co2[0]) < mmd->tolerance) ) + BMO_Insert_MapPointer(bm, &extop, BMOP_EXFACE_EXCLUDEMAP, edge, NULL); + + if (mmd->flag & MOD_MIR_AXIS_Y) + if ( (fabs(co1[1]) < mmd->tolerance) && + (fabs(co2[1]) < mmd->tolerance) ) + BMO_Insert_MapPointer(bm, &extop, BMOP_EXFACE_EXCLUDEMAP, edge, NULL); + + if (mmd->flag & MOD_MIR_AXIS_Z) + if ( (fabs(co1[2]) < mmd->tolerance) && + (fabs(co2[2]) < mmd->tolerance) ) + BMO_Insert_MapPointer(bm, &extop, BMOP_EXFACE_EXCLUDEMAP, edge, NULL); + } + } + } + } + } + + + BMO_Exec_Op(bm, &extop); + + el = BMO_IterNew(&siter, bm, &extop, BMOP_EXFACE_MULTOUT); + for (; el; el=BMO_IterStep(&siter)) { + BM_Select(bm, el, 1); + } + + BMO_Finish_Op(bm, &extop); + + if(nor[0]==0.0 && nor[1]==0.0 && nor[2]==0.0) return 'g'; // grab + return 'n'; // normal constraint + +} + + +static short extrudeflag_edge(Object *obedit, EditMesh *em, short flag, float *nor) { + short ret; + EditMesh *em2; + BMesh *bm = editmesh_to_bmesh(em); + + ret = BM_extrude_edgeflag(obedit, bm, flag, nor); + em2 = bmesh_to_editmesh(bm); + + set_editMesh(em, em2); + MEM_freeN(em2); + + EM_select_flush(em); + + return ret; +} /* this is actually a recode of extrudeflag(), using proper edge/face select */ /* hurms, doesnt use 'flag' yet, but its not called by primitive making stuff anyway */ -static short extrudeflag_edge(Object *obedit, EditMesh *em, short flag, float *nor) +static short extrudeflag_edge_old(Object *obedit, EditMesh *em, short flag, float *nor) { /* all select edges/faces: extrude */ /* old select is cleared, in new ones it is set */ |