Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
path: root/source
diff options
context:
space:
mode:
authorJoseph Eagar <joeedh@gmail.com>2009-07-17 14:54:00 +0400
committerJoseph Eagar <joeedh@gmail.com>2009-07-17 14:54:00 +0400
commitf2138686d9d8c105ebf8884774fd7e4d8ff239a1 (patch)
treed7ee0a0c846f373a91d9006fe17b2a82b27b0f47 /source
parent359fb502b676d5826c5113c05d3bd1731087de7c (diff)
moved the selection history stuff within bmesh itself, to avoid memory access problems. also committing some playing around I did with the edge subdivide code, which isn't doesn't really completely work.
Diffstat (limited to 'source')
-rw-r--r--source/blender/blenkernel/BKE_tessmesh.h12
-rw-r--r--source/blender/bmesh/bmesh.h3
-rw-r--r--source/blender/bmesh/bmesh_marking.h15
-rw-r--r--source/blender/bmesh/intern/bmesh_construct.c43
-rw-r--r--source/blender/bmesh/intern/bmesh_marking.c189
-rw-r--r--source/blender/bmesh/intern/bmesh_polygon.c52
-rw-r--r--source/blender/bmesh/intern/bmesh_structure.c5
-rw-r--r--source/blender/bmesh/operators/mesh_conv.c1
-rw-r--r--source/blender/bmesh/operators/subdivideop.c113
-rw-r--r--source/blender/editors/mesh/bmesh_select.c16
-rw-r--r--source/blender/editors/mesh/bmesh_selecthistory.c160
-rw-r--r--source/blender/editors/mesh/bmeshutils.c4
-rw-r--r--source/blender/editors/space_view3d/drawobject.c4
-rw-r--r--source/blender/editors/transform/transform_conversions.c4
14 files changed, 415 insertions, 206 deletions
diff --git a/source/blender/blenkernel/BKE_tessmesh.h b/source/blender/blenkernel/BKE_tessmesh.h
index c3ccf4b1e6a..e448f904841 100644
--- a/source/blender/blenkernel/BKE_tessmesh.h
+++ b/source/blender/blenkernel/BKE_tessmesh.h
@@ -11,13 +11,6 @@ ok: the EDBM module is for editmode bmesh stuff. in contrast, the
the BMEditMesh structure.
*/
-typedef struct BMEditSelection
-{
- struct BMEditSelection *next, *prev;
- short type;
- void *data;
-} BMEditSelection;
-
/*this structure replaces EditMesh.
through this, you get access to both the edit bmesh,
@@ -25,7 +18,7 @@ typedef struct BMEditSelection
struct itself.
the entire derivedmesh and modifier system works with this structure,
- and not BMesh. Mesh->editbmesh will store a pointer to this structure.*/
+ and not BMesh. Mesh->edit_bmesh stores a pointer to this structure.*/
typedef struct BMEditMesh {
struct BMesh *bm;
@@ -50,9 +43,6 @@ typedef struct BMEditMesh {
struct BMVert **vert_index;
struct BMEdge **edge_index;
struct BMFace **face_index;
-
- /*selection order list*/
- ListBase selected;
/*selection mode*/
int selectmode;
diff --git a/source/blender/bmesh/bmesh.h b/source/blender/bmesh/bmesh.h
index ba5b26444c0..3c8194ee205 100644
--- a/source/blender/bmesh/bmesh.h
+++ b/source/blender/bmesh/bmesh.h
@@ -170,6 +170,9 @@ typedef struct BMesh {
int totflags, walkers; /*total number of tool flag layers*/
ListBase errorstack;
+ /*selection order list*/
+ ListBase selected;
+
/*active face pointer*/
struct BMFace *act_face;
} BMesh;
diff --git a/source/blender/bmesh/bmesh_marking.h b/source/blender/bmesh/bmesh_marking.h
index 1074b057eba..dbe6a867385 100644
--- a/source/blender/bmesh/bmesh_marking.h
+++ b/source/blender/bmesh/bmesh_marking.h
@@ -1,6 +1,13 @@
#ifndef BM_MARKING_H
#define BM_MARKING_H
+typedef struct BMEditSelection
+{
+ struct BMEditSelection *next, *prev;
+ short type;
+ void *data;
+} BMEditSelection;
+
/*Selection code*/
void BM_Select_Vert(struct BMesh *bm, struct BMVert *v, int select);
void BM_Select_Edge(struct BMesh *bm, struct BMEdge *e, int select);
@@ -13,4 +20,12 @@ int BM_CountFlag(struct BMesh *bm, int type, int flag);
void BM_Select(struct BMesh *bm, void *element, int select);
int BM_Is_Selected(BMesh *bm, void *element);
+/*edit selection stuff*/
+void BM_editselection_center(BMesh *bm, float *center, BMEditSelection *ese);
+void BM_editselection_normal(float *normal, BMEditSelection *ese);
+void BM_editselection_plane(BMesh *bm, float *plane, BMEditSelection *ese);
+void BM_remove_selection(BMesh *bm, void *data);
+void BM_store_selection(BMesh *bm, void *data);
+void BM_validate_selections(BMesh *bm);
+
#endif
diff --git a/source/blender/bmesh/intern/bmesh_construct.c b/source/blender/bmesh/intern/bmesh_construct.c
index 58025fd33cc..06b7116de59 100644
--- a/source/blender/bmesh/intern/bmesh_construct.c
+++ b/source/blender/bmesh/intern/bmesh_construct.c
@@ -418,11 +418,12 @@ BMesh *BM_Copy_Mesh(BMesh *bmold)
V_DECLARE(etable);
BMLoop *l, *l2, **loops = NULL;
V_DECLARE(loops);
- BMFace *f, *f2;
-
+ BMFace *f, *f2, **ftable = NULL;
+ V_DECLARE(ftable);
+ BMEditSelection *ese;
BMIter iter, liter;
int allocsize[4] = {512,512,2048,512}, numTex, numCol;
- int i;
+ int i, j;
/*allocate a bmesh*/
bm = BM_Make_Mesh(allocsize);
@@ -468,15 +469,15 @@ BMesh *BM_Copy_Mesh(BMesh *bmold)
}
f = BMIter_New(&iter, bmold, BM_FACES_OF_MESH, NULL);
- for (; f; f=BMIter_Step(&iter)) {
+ for (i=0; f; f=BMIter_Step(&iter), i++) {
V_RESET(loops);
V_RESET(edges);
l = BMIter_New(&liter, bmold, BM_LOOPS_OF_FACE, f);
- for (i=0; i<f->len; i++, l = BMIter_Step(&liter)) {
+ for (j=0; j<f->len; j++, l = BMIter_Step(&liter)) {
V_GROW(loops);
V_GROW(edges);
- loops[i] = l;
- edges[i] = etable[BMINDEX_GET(l->e)];
+ loops[j] = l;
+ edges[j] = etable[BMINDEX_GET(l->e)];
}
v = vtable[BMINDEX_GET(loops[0]->v)];
@@ -488,19 +489,41 @@ BMesh *BM_Copy_Mesh(BMesh *bmold)
}
f2 = BM_Make_Ngon(bm, v, v2, edges, f->len, 0);
+
+ BMINDEX_SET(f, i);
+ V_GROW(ftable);
+ ftable[i] = f2;
+
BM_Copy_Attributes(bmold, bm, f, f2);
VECCOPY(f2->no, f->no);
l = BMIter_New(&liter, bm, BM_LOOPS_OF_FACE, f2);
- for (i=0; i<f->len; i++, l = BMIter_Step(&liter)) {
- BM_Copy_Attributes(bmold, bm, loops[i], l);
+ for (j=0; j<f->len; j++, l = BMIter_Step(&liter)) {
+ BM_Copy_Attributes(bmold, bm, loops[j], l);
}
if (f == bmold->act_face) bm->act_face = f2;
}
-
+
+ /*copy over edit selection history*/
+ for (ese=bmold->selected.first; ese; ese=ese->next) {
+ void *ele;
+
+ if (ese->type == BM_VERT)
+ ele = vtable[BMINDEX_GET(ese->data)];
+ else if (ese->type == BM_EDGE)
+ ele = etable[BMINDEX_GET(ese->data)];
+ else if (ese->type == BM_FACE) {
+ ele = ftable[BMINDEX_GET(ese->data)];
+ }
+
+ BM_store_selection(bm, ele);
+ }
+
V_FREE(etable);
V_FREE(vtable);
+ V_FREE(ftable);
+
V_FREE(loops);
V_FREE(edges);
diff --git a/source/blender/bmesh/intern/bmesh_marking.c b/source/blender/bmesh/intern/bmesh_marking.c
index 5923add3025..578e7646b2d 100644
--- a/source/blender/bmesh/intern/bmesh_marking.c
+++ b/source/blender/bmesh/intern/bmesh_marking.c
@@ -1,7 +1,14 @@
-#include <string.h>
+#include "MEM_guardedalloc.h"
+
+#include "BKE_utildefines.h"
+
+#include "BLI_arithb.h"
+#include "BLI_blenlib.h"
+
#include "bmesh.h"
#include "bmesh_private.h"
+#include <string.h>
/*
* BM_MARK.C
@@ -304,4 +311,182 @@ int BM_Is_Selected(BMesh *bm, void *element)
{
BMHeader *head = element;
return BM_TestHFlag(head, BM_SELECT);
-} \ No newline at end of file
+}
+
+
+/* generic way to get data from an EditSelection type
+These functions were written to be used by the Modifier widget when in Rotate about active mode,
+but can be used anywhere.
+EM_editselection_center
+EM_editselection_normal
+EM_editselection_plane
+*/
+void BM_editselection_center(BMesh *em, float *center, BMEditSelection *ese)
+{
+ if (ese->type==BM_VERT) {
+ BMVert *eve= ese->data;
+ VecCopyf(center, eve->co);
+ } else if (ese->type==BM_EDGE) {
+ BMEdge *eed= ese->data;
+ VecAddf(center, eed->v1->co, eed->v2->co);
+ VecMulf(center, 0.5);
+ } else if (ese->type==BM_FACE) {
+ BMFace *efa= ese->data;
+ BM_Compute_Face_Center(em, efa, center);
+ }
+}
+
+void BM_editselection_normal(float *normal, BMEditSelection *ese)
+{
+ if (ese->type==BM_VERT) {
+ BMVert *eve= ese->data;
+ VecCopyf(normal, eve->no);
+ } else if (ese->type==BM_EDGE) {
+ BMEdge *eed= ese->data;
+ float plane[3]; /* need a plane to correct the normal */
+ float vec[3]; /* temp vec storage */
+
+ VecAddf(normal, eed->v1->no, eed->v2->no);
+ VecSubf(plane, eed->v2->co, eed->v1->co);
+
+ /* the 2 vertex normals will be close but not at rightangles to the edge
+ for rotate about edge we want them to be at right angles, so we need to
+ do some extra colculation to correct the vert normals,
+ we need the plane for this */
+ Crossf(vec, normal, plane);
+ Crossf(normal, plane, vec);
+ Normalize(normal);
+
+ } else if (ese->type==BM_FACE) {
+ BMFace *efa= ese->data;
+ VecCopyf(normal, efa->no);
+ }
+}
+
+/* Calculate a plane that is rightangles to the edge/vert/faces normal
+also make the plane run allong an axis that is related to the geometry,
+because this is used for the manipulators Y axis.*/
+void BM_editselection_plane(BMesh *em, float *plane, BMEditSelection *ese)
+{
+ if (ese->type==BM_VERT) {
+ BMVert *eve= ese->data;
+ float vec[3]={0,0,0};
+
+ if (ese->prev) { /*use previously selected data to make a usefull vertex plane */
+ BM_editselection_center(em, vec, ese->prev);
+ VecSubf(plane, vec, eve->co);
+ } else {
+ /* make a fake plane thats at rightangles to the normal
+ we cant make a crossvec from a vec thats the same as the vec
+ unlikely but possible, so make sure if the normal is (0,0,1)
+ that vec isnt the same or in the same direction even.*/
+ if (eve->no[0]<0.5) vec[0]=1;
+ else if (eve->no[1]<0.5) vec[1]=1;
+ else vec[2]=1;
+ Crossf(plane, eve->no, vec);
+ }
+ } else if (ese->type==BM_EDGE) {
+ BMEdge *eed= ese->data;
+
+ /*the plane is simple, it runs allong the edge
+ however selecting different edges can swap the direction of the y axis.
+ this makes it less likely for the y axis of the manipulator
+ (running along the edge).. to flip less often.
+ at least its more pradictable */
+ if (eed->v2->co[1] > eed->v1->co[1]) /*check which to do first */
+ VecSubf(plane, eed->v2->co, eed->v1->co);
+ else
+ VecSubf(plane, eed->v1->co, eed->v2->co);
+
+ } else if (ese->type==BM_FACE) {
+ BMFace *efa= ese->data;
+ float vec[3] = {0.0f, 0.0f, 0.0f};
+
+ /*for now, use face normal*/
+
+ /* make a fake plane thats at rightangles to the normal
+ we cant make a crossvec from a vec thats the same as the vec
+ unlikely but possible, so make sure if the normal is (0,0,1)
+ that vec isnt the same or in the same direction even.*/
+ if (efa->no[0]<0.5) vec[0]=1.0f;
+ else if (efa->no[1]<0.5) vec[1]=1.0f;
+ else vec[2]=1.0f;
+ Crossf(plane, efa->no, vec);
+#if 0
+
+ if (efa->v4) { /*if its a quad- set the plane along the 2 longest edges.*/
+ float vecA[3], vecB[3];
+ VecSubf(vecA, efa->v4->co, efa->v3->co);
+ VecSubf(vecB, efa->v1->co, efa->v2->co);
+ VecAddf(plane, vecA, vecB);
+
+ VecSubf(vecA, efa->v1->co, efa->v4->co);
+ VecSubf(vecB, efa->v2->co, efa->v3->co);
+ VecAddf(vec, vecA, vecB);
+ /*use the biggest edge length*/
+ if (plane[0]*plane[0]+plane[1]*plane[1]+plane[2]*plane[2] < vec[0]*vec[0]+vec[1]*vec[1]+vec[2]*vec[2])
+ VecCopyf(plane, vec);
+ } else {
+ /*start with v1-2 */
+ VecSubf(plane, efa->v1->co, efa->v2->co);
+
+ /*test the edge between v2-3, use if longer */
+ VecSubf(vec, efa->v2->co, efa->v3->co);
+ if (plane[0]*plane[0]+plane[1]*plane[1]+plane[2]*plane[2] < vec[0]*vec[0]+vec[1]*vec[1]+vec[2]*vec[2])
+ VecCopyf(plane, vec);
+
+ /*test the edge between v1-3, use if longer */
+ VecSubf(vec, efa->v3->co, efa->v1->co);
+ if (plane[0]*plane[0]+plane[1]*plane[1]+plane[2]*plane[2] < vec[0]*vec[0]+vec[1]*vec[1]+vec[2]*vec[2])
+ VecCopyf(plane, vec);
+ }
+#endif
+ }
+ Normalize(plane);
+}
+
+static int BM_check_selection(BMesh *em, void *data)
+{
+ BMEditSelection *ese;
+
+ for(ese = em->selected.first; ese; ese = ese->next){
+ if(ese->data == data) return 1;
+ }
+
+ return 0;
+}
+
+void BM_remove_selection(BMesh *em, void *data)
+{
+ BMEditSelection *ese;
+ for(ese=em->selected.first; ese; ese = ese->next){
+ if(ese->data == data){
+ BLI_freelinkN(&(em->selected),ese);
+ break;
+ }
+ }
+}
+
+void BM_store_selection(BMesh *em, void *data)
+{
+ BMEditSelection *ese;
+ if(!BM_check_selection(em, data)){
+ ese = (BMEditSelection*) MEM_callocN( sizeof(BMEditSelection), "BMEdit Selection");
+ ese->type = ((BMHeader*)data)->type;
+ ese->data = data;
+ BLI_addtail(&(em->selected),ese);
+ }
+}
+
+void BM_validate_selections(BMesh *em)
+{
+ BMEditSelection *ese, *nextese;
+
+ ese = em->selected.first;
+
+ while(ese){
+ nextese = ese->next;
+ if (!BM_TestHFlag(ese->data, BM_SELECT)) BLI_freelinkN(&(em->selected), ese);
+ ese = nextese;
+ }
+}
diff --git a/source/blender/bmesh/intern/bmesh_polygon.c b/source/blender/bmesh/intern/bmesh_polygon.c
index c013952a622..9df2bb8c202 100644
--- a/source/blender/bmesh/intern/bmesh_polygon.c
+++ b/source/blender/bmesh/intern/bmesh_polygon.c
@@ -83,12 +83,14 @@ static int point_in_triangle(double *v1, double *v2, double *v3, double *pt)
* computing newell normal.
*
*/
+#define FEQ(f1, f2) (ABS((double)(f1)-(double)(f2)) < 0.1)
+
static void compute_poly_normal(float normal[3], float (*verts)[3], int nverts)
{
- float *u, *v;/*, *w, v1[3], v2[3];*/
- double n[3] = {0.0, 0.0, 0.0}, l;
- int i;
+ double u[3], v[3], w[3];/*, *w, v1[3], v2[3];*/
+ double n[3] = {0.0, 0.0, 0.0}, l, v1[3], v2[3];
+ int i, s=0;
/*this fixes some weird numerical error*/
verts[0][0] += 0.0001f;
@@ -96,9 +98,19 @@ static void compute_poly_normal(float normal[3], float (*verts)[3], int nverts)
verts[0][2] += 0.0001f;
for(i = 0; i < nverts; i++){
- u = verts[i];
- v = verts[(i+1) % nverts];
+ VECCOPY(u, verts[i]);
+ VECCOPY(v, verts[(i+1) % nverts]);
+ VECCOPY(w, verts[(i+2) % nverts]);
+ VECSUB(v1, w, v);
+ VECSUB(v2, v, u);
+ Normalize_d(v1);
+ Normalize_d(v2);
+
+ l = INPR(v1, v2);
+ if (l < 0.01 && l > -0.01)
+ continue;
+
/* newell's method
so thats?:
@@ -472,7 +484,7 @@ int linecrosses(double *v1, double *v2, double *v3, double *v4)
note, there could be more winding cases then there needs to be. */
int linecrossesf(float *v1, float *v2, float *v3, float *v4)
{
- int w1, w2, w3, w4, w5;
+ int w1, w2, w3, w4, w5, ret;
/* int test1_a, test1_a, test2_a, test2_a;
@@ -504,12 +516,38 @@ int linecrossesf(float *v1, float *v2, float *v3, float *v4)
return (w1 == w2) && (w2 == w3) && (w3 == w4);*/
+ /*do an interval test on the x and y axes*/
+ /*first do x axis*/
+ #define T 0.01
+ if (ABS(v1[1]-v2[1]) < T && ABS(v3[1]-v4[1]) < T &&
+ ABS(v1[1]-v3[1]) < T) {
+ if (v3[0] >= v1[0] && v3[0] <= v2[0])
+ return 1;
+ if (v4[0] >= v1[0] && v4[0] <= v2[0])
+ return 1;
+ if (v3[0] <= v1[0] && v4[0] >= v2[0])
+ return 1;
+ }
+
+ /*now do y axis*/
+ if (ABS(v1[0]-v2[0]) < T && ABS(v3[0]-v4[0]) < T &&
+ ABS(v1[0]-v3[0]) < T) {
+ if (v3[1] >= v1[1] && v3[1] <= v2[1])
+ return 1;
+ if (v4[1] >= v1[1] && v4[1] <= v2[1])
+ return 1;
+ if (v3[1] <= v1[1] && v4[1] >= v2[1])
+ return 1;
+ }
+
+ /*now test winding*/
w1 = testedgesidef(v1, v3, v2);
w2 = testedgesidef(v2, v4, v1);
w3 = !testedgesidef(v1, v2, v3);
w4 = testedgesidef(v3, v2, v4);
w5 = !testedgesidef(v3, v1, v4);
- return w1 == w2 && w2 == w3 && w3 == w4 && w4==w5;
+
+ return w1 == w2 && w2 == w3 && w3 == w4 && w4==w5;
}
int goodline(float (*projectverts)[3], BMFace *f, int v1i,
diff --git a/source/blender/bmesh/intern/bmesh_structure.c b/source/blender/bmesh/intern/bmesh_structure.c
index a14f1d662ae..664e07f805b 100644
--- a/source/blender/bmesh/intern/bmesh_structure.c
+++ b/source/blender/bmesh/intern/bmesh_structure.c
@@ -195,12 +195,16 @@ BMFace *bmesh_addpolylist(BMesh *bm, BMFace *example){
*/
void bmesh_free_vert(BMesh *bm, BMVert *v){
bm->totvert--;
+ BM_remove_selection(bm, v);
+
CustomData_bmesh_free_block(&bm->vdata, &v->head.data);
BLI_mempool_free(bm->flagpool, v->head.flags);
BLI_mempool_free(bm->vpool, v);
}
void bmesh_free_edge(BMesh *bm, BMEdge *e){
bm->totedge--;
+ BM_remove_selection(bm, e);
+
CustomData_bmesh_free_block(&bm->edata, &e->head.data);
BLI_mempool_free(bm->flagpool, e->head.flags);
BLI_mempool_free(bm->epool, e);
@@ -208,6 +212,7 @@ void bmesh_free_edge(BMesh *bm, BMEdge *e){
void bmesh_free_poly(BMesh *bm, BMFace *f){
if (f == bm->act_face)
bm->act_face = NULL;
+ BM_remove_selection(bm, f);
bm->totface--;
CustomData_bmesh_free_block(&bm->pdata, &f->head.data);
diff --git a/source/blender/bmesh/operators/mesh_conv.c b/source/blender/bmesh/operators/mesh_conv.c
index 26dd9026320..9944c9b8d23 100644
--- a/source/blender/bmesh/operators/mesh_conv.c
+++ b/source/blender/bmesh/operators/mesh_conv.c
@@ -131,6 +131,7 @@ void mesh_to_bmesh_exec(BMesh *bm, BMOperator *op) {
f = BM_Make_Ngon(bm, v1, v2, fedges, mpoly->totloop, 0);
f->head.flag = MEFlags_To_BMFlags(mpoly->flag, BM_FACE);
+ f->mat_nr = mpoly->mat_nr;
if (i == me->act_face) bm->act_face = f;
/*Copy over loop customdata*/
diff --git a/source/blender/bmesh/operators/subdivideop.c b/source/blender/bmesh/operators/subdivideop.c
index 21da2775070..7164ed9f121 100644
--- a/source/blender/bmesh/operators/subdivideop.c
+++ b/source/blender/bmesh/operators/subdivideop.c
@@ -607,6 +607,7 @@ subdpattern *patterns[] = {
typedef struct subd_facedata {
BMVert *start; subdpattern *pat;
+ int totedgesel; //only used if pat was NULL, e.g. no pattern was found
} subd_facedata;
void esubdivide_exec(BMesh *bmesh, BMOperator *op)
@@ -623,9 +624,12 @@ void esubdivide_exec(BMesh *bmesh, BMOperator *op)
subdparams params;
subd_facedata *facedata = NULL;
V_DECLARE(facedata);
+ BMLoop *l, **splits = NULL, **loops = NULL;
+ V_DECLARE(splits);
+ V_DECLARE(loops);
float smooth, fractal;
int beauty;
- int i, j, matched, a, b, numcuts;
+ int i, j, matched, a, b, numcuts, totesel;
BMO_Flag_Buffer(bmesh, op, "edges", SUBD_SPLIT);
@@ -658,13 +662,20 @@ void esubdivide_exec(BMesh *bmesh, BMOperator *op)
V_RESET(edges);
V_RESET(verts);
+ matched = 0;
+
i = 0;
+ totesel = 0;
for (nl=BMIter_New(&liter, bmesh, BM_LOOPS_OF_FACE, face);
nl; nl=BMIter_Step(&liter)) {
V_GROW(edges);
V_GROW(verts);
edges[i] = nl->e;
verts[i] = nl->v;
+
+ if (BMO_TestFlag(bmesh, edges[i], SUBD_SPLIT))
+ totesel++;
+
i++;
}
@@ -703,26 +714,37 @@ void esubdivide_exec(BMesh *bmesh, BMOperator *op)
pat = patterns[i];
if (pat->len == face->len) {
for (a=0; a<pat->len; a++) {
- matched = 1;
- for (b=0; b<pat->len; b++) {
- j = (b + a) % pat->len;
- if ((!!BMO_TestFlag(bmesh, edges[j], SUBD_SPLIT))
- != (!!pat->seledges[b])) {
- matched = 0;
- break;
+ matched = 1;
+ for (b=0; b<pat->len; b++) {
+ j = (b + a) % pat->len;
+ if ((!!BMO_TestFlag(bmesh, edges[j], SUBD_SPLIT))
+ != (!!pat->seledges[b])) {
+ matched = 0;
+ break;
+ }
}
- }
- if (matched) break;
+ if (matched) break;
}
if (matched) {
V_GROW(facedata);
- BMO_SetFlag(bmesh, face, SUBD_SPLIT);
j = V_COUNT(facedata) - 1;
+
+ BMO_SetFlag(bmesh, face, SUBD_SPLIT);
+
facedata[j].pat = pat;
facedata[j].start = verts[a];
break;
}
}
+
+ }
+
+ if (!matched && totesel) {
+ V_GROW(facedata);
+ j = V_COUNT(facedata) - 1;
+
+ BMO_SetFlag(bmesh, face, SUBD_SPLIT);
+ facedata[j].totedgesel = totesel;
}
}
@@ -743,10 +765,73 @@ void esubdivide_exec(BMesh *bmesh, BMOperator *op)
face; face=BMIter_Step(&fiter)) {
/*figure out which pattern to use*/
V_RESET(verts);
- if (BMO_TestFlag(bmesh, face, SUBD_SPLIT) == 0) continue;
+ if (BMO_TestFlag(bmesh, face, SUBD_SPLIT) == 0)
+ continue;
pat = facedata[i].pat;
- if (!pat) continue;
+ if (!pat && facedata[i].totedgesel == 2) { /*ok, no pattern. we still may be able to do something.*/
+ BMFace *nf;
+ int vlen;
+
+ V_RESET(loops);
+ V_RESET(splits);
+
+ /*for case of two edges, connecting them shouldn't be too hard*/
+ BM_ITER(l, &liter, bmesh, BM_LOOPS_OF_FACE, face) {
+ V_GROW(loops);
+ loops[V_COUNT(loops)-1] = l;
+ }
+
+ vlen = V_COUNT(loops);
+
+ /*find the boundary of one of the split edges*/
+ for (a=1; a<vlen; a++) {
+ if (!BMO_TestFlag(bmesh, loops[a-1]->v, ELE_INNER)
+ && BMO_TestFlag(bmesh, loops[a]->v, ELE_INNER))
+ break;
+ }
+
+ if (BMO_TestFlag(bmesh, loops[(a+numcuts+1)%vlen]->v, ELE_INNER)) {
+ b = (a+numcuts+1)%vlen;
+ } else {
+ /*find the boundary of the other edge.*/
+ for (j=0; j<vlen; j++) {
+ b = (j + a + numcuts + 1) % vlen;
+ if (!BMO_TestFlag(bmesh, loops[b==0 ? vlen-1 : b-1]->v, ELE_INNER)
+ && BMO_TestFlag(bmesh, loops[b]->v, ELE_INNER))
+ break;
+ }
+ }
+
+ b += numcuts - 1;
+
+ for (j=0; j<numcuts; j++) {
+ V_GROW(splits);
+ splits[V_COUNT(splits)-1] = loops[a];
+
+ V_GROW(splits);
+ splits[V_COUNT(splits)-1] = loops[b];
+
+ b = (b-1) % vlen;
+ a = (a+1) % vlen;
+ }
+
+ BM_LegalSplits(bmesh, face, splits, V_COUNT(splits)/2);
+
+ for (j=0; j<V_COUNT(splits)/2; j++) {
+ if (splits[j*2]) {
+ BMFace *nf;
+
+ nf = BM_Split_Face(bmesh, face, splits[j*a]->v, splits[j*2+1]->v, &nl, NULL);
+ }
+ }
+
+ i++;
+ continue;
+ } else if (!pat) {
+ i++;
+ continue;
+ }
j = a = 0;
for (nl=BMIter_New(&liter, bmesh, BM_LOOPS_OF_FACE, face);
@@ -777,6 +862,8 @@ void esubdivide_exec(BMesh *bmesh, BMOperator *op)
if (facedata) V_FREE(facedata);
if (edges) V_FREE(edges);
if (verts) V_FREE(verts);
+ V_FREE(splits);
+ V_FREE(loops);
BMO_Flag_To_Slot(bmesh, op, "outinner",
ELE_INNER, BM_ALL);
diff --git a/source/blender/editors/mesh/bmesh_select.c b/source/blender/editors/mesh/bmesh_select.c
index c4f2a294d0b..760bb5b65e0 100644
--- a/source/blender/editors/mesh/bmesh_select.c
+++ b/source/blender/editors/mesh/bmesh_select.c
@@ -1140,8 +1140,8 @@ static void mouse_mesh_shortest_path(bContext *C, short mval[2])
Mesh *me= vc.obedit->data;
int path = 0;
- if (em->selected.last) {
- EditSelection *ese = em->selected.last;
+ if (em->bm->selected.last) {
+ EditSelection *ese = em->bm->selected.last;
if(ese && ese->type == BMEdge) {
BMEdge *eed_act;
@@ -1292,26 +1292,26 @@ static void EDBM_strip_selections(BMEditMesh *em)
BMEditSelection *ese, *nextese;
if(!(em->selectmode & SCE_SELECT_VERTEX)){
- ese = em->selected.first;
+ ese = em->bm->selected.first;
while(ese){
nextese = ese->next;
- if(ese->type == BM_VERT) BLI_freelinkN(&(em->selected),ese);
+ if(ese->type == BM_VERT) BLI_freelinkN(&(em->bm->selected),ese);
ese = nextese;
}
}
if(!(em->selectmode & SCE_SELECT_EDGE)){
- ese=em->selected.first;
+ ese=em->bm->selected.first;
while(ese){
nextese = ese->next;
- if(ese->type == BM_EDGE) BLI_freelinkN(&(em->selected), ese);
+ if(ese->type == BM_EDGE) BLI_freelinkN(&(em->bm->selected), ese);
ese = nextese;
}
}
if(!(em->selectmode & SCE_SELECT_FACE)){
- ese=em->selected.first;
+ ese=em->bm->selected.first;
while(ese){
nextese = ese->next;
- if(ese->type == BM_FACE) BLI_freelinkN(&(em->selected), ese);
+ if(ese->type == BM_FACE) BLI_freelinkN(&(em->bm->selected), ese);
ese = nextese;
}
}
diff --git a/source/blender/editors/mesh/bmesh_selecthistory.c b/source/blender/editors/mesh/bmesh_selecthistory.c
index 9421a98a11c..5fb19dc1648 100644
--- a/source/blender/editors/mesh/bmesh_selecthistory.c
+++ b/source/blender/editors/mesh/bmesh_selecthistory.c
@@ -88,57 +88,19 @@
#include "BLO_sys_types.h" // for intptr_t support
-/* XXX */
-static void waitcursor() {}
-static int pupmenu() {return 0;}
+/*these wrap equivilent bmesh functions. I'm in two minds of it we should
+ just use the bm functions directly; on the one hand, there's no real
+ need (at the moment) to wrap them, but on the other hand having these
+ wrapped avoids a confusing mess of mixing BM_ and EDBM_ namespaces.*/
-/* generic way to get data from an EditSelection type
-These functions were written to be used by the Modifier widget when in Rotate about active mode,
-but can be used anywhere.
-EM_editselection_center
-EM_editselection_normal
-EM_editselection_plane
-*/
void EDBM_editselection_center(BMEditMesh *em, float *center, BMEditSelection *ese)
{
- if (ese->type==BM_VERT) {
- BMVert *eve= ese->data;
- VecCopyf(center, eve->co);
- } else if (ese->type==BM_EDGE) {
- BMEdge *eed= ese->data;
- VecAddf(center, eed->v1->co, eed->v2->co);
- VecMulf(center, 0.5);
- } else if (ese->type==BM_FACE) {
- BMFace *efa= ese->data;
- BM_Compute_Face_Center(em->bm, efa, center);
- }
+ BM_editselection_center(em->bm, center, ese);
}
void EDBM_editselection_normal(float *normal, BMEditSelection *ese)
{
- if (ese->type==BM_VERT) {
- BMVert *eve= ese->data;
- VecCopyf(normal, eve->no);
- } else if (ese->type==BM_EDGE) {
- BMEdge *eed= ese->data;
- float plane[3]; /* need a plane to correct the normal */
- float vec[3]; /* temp vec storage */
-
- VecAddf(normal, eed->v1->no, eed->v2->no);
- VecSubf(plane, eed->v2->co, eed->v1->co);
-
- /* the 2 vertex normals will be close but not at rightangles to the edge
- for rotate about edge we want them to be at right angles, so we need to
- do some extra colculation to correct the vert normals,
- we need the plane for this */
- Crossf(vec, normal, plane);
- Crossf(normal, plane, vec);
- Normalize(normal);
-
- } else if (ese->type==BM_FACE) {
- BMFace *efa= ese->data;
- VecCopyf(normal, efa->no);
- }
+ BM_editselection_normal(normal, ese);
}
/* Calculate a plane that is rightangles to the edge/vert/faces normal
@@ -146,125 +108,25 @@ also make the plane run allong an axis that is related to the geometry,
because this is used for the manipulators Y axis.*/
void EDBM_editselection_plane(BMEditMesh *em, float *plane, BMEditSelection *ese)
{
- if (ese->type==BM_VERT) {
- BMVert *eve= ese->data;
- float vec[3]={0,0,0};
-
- if (ese->prev) { /*use previously selected data to make a usefull vertex plane */
- EDBM_editselection_center(em, vec, ese->prev);
- VecSubf(plane, vec, eve->co);
- } else {
- /* make a fake plane thats at rightangles to the normal
- we cant make a crossvec from a vec thats the same as the vec
- unlikely but possible, so make sure if the normal is (0,0,1)
- that vec isnt the same or in the same direction even.*/
- if (eve->no[0]<0.5) vec[0]=1;
- else if (eve->no[1]<0.5) vec[1]=1;
- else vec[2]=1;
- Crossf(plane, eve->no, vec);
- }
- } else if (ese->type==BM_EDGE) {
- BMEdge *eed= ese->data;
-
- /*the plane is simple, it runs allong the edge
- however selecting different edges can swap the direction of the y axis.
- this makes it less likely for the y axis of the manipulator
- (running along the edge).. to flip less often.
- at least its more pradictable */
- if (eed->v2->co[1] > eed->v1->co[1]) /*check which to do first */
- VecSubf(plane, eed->v2->co, eed->v1->co);
- else
- VecSubf(plane, eed->v1->co, eed->v2->co);
-
- } else if (ese->type==BM_FACE) {
- BMFace *efa= ese->data;
- float vec[3] = {0.0f, 0.0f, 0.0f};
-
- /*for now, use face normal*/
-
- /* make a fake plane thats at rightangles to the normal
- we cant make a crossvec from a vec thats the same as the vec
- unlikely but possible, so make sure if the normal is (0,0,1)
- that vec isnt the same or in the same direction even.*/
- if (efa->no[0]<0.5) vec[0]=1.0f;
- else if (efa->no[1]<0.5) vec[1]=1.0f;
- else vec[2]=1.0f;
- Crossf(plane, efa->no, vec);
-#if 0
-
- if (efa->v4) { /*if its a quad- set the plane along the 2 longest edges.*/
- float vecA[3], vecB[3];
- VecSubf(vecA, efa->v4->co, efa->v3->co);
- VecSubf(vecB, efa->v1->co, efa->v2->co);
- VecAddf(plane, vecA, vecB);
-
- VecSubf(vecA, efa->v1->co, efa->v4->co);
- VecSubf(vecB, efa->v2->co, efa->v3->co);
- VecAddf(vec, vecA, vecB);
- /*use the biggest edge length*/
- if (plane[0]*plane[0]+plane[1]*plane[1]+plane[2]*plane[2] < vec[0]*vec[0]+vec[1]*vec[1]+vec[2]*vec[2])
- VecCopyf(plane, vec);
- } else {
- /*start with v1-2 */
- VecSubf(plane, efa->v1->co, efa->v2->co);
-
- /*test the edge between v2-3, use if longer */
- VecSubf(vec, efa->v2->co, efa->v3->co);
- if (plane[0]*plane[0]+plane[1]*plane[1]+plane[2]*plane[2] < vec[0]*vec[0]+vec[1]*vec[1]+vec[2]*vec[2])
- VecCopyf(plane, vec);
-
- /*test the edge between v1-3, use if longer */
- VecSubf(vec, efa->v3->co, efa->v1->co);
- if (plane[0]*plane[0]+plane[1]*plane[1]+plane[2]*plane[2] < vec[0]*vec[0]+vec[1]*vec[1]+vec[2]*vec[2])
- VecCopyf(plane, vec);
- }
-#endif
- }
- Normalize(plane);
+ BM_editselection_plane(em->bm, plane, ese);
}
static int EDBM_check_selection(BMEditMesh *em, void *data)
{
- BMEditSelection *ese;
-
- for(ese = em->selected.first; ese; ese = ese->next){
- if(ese->data == data) return 1;
- }
-
- return 0;
+ BM_check_selection(em, data);
}
void EDBM_remove_selection(BMEditMesh *em, void *data)
{
- BMEditSelection *ese;
- for(ese=em->selected.first; ese; ese = ese->next){
- if(ese->data == data){
- BLI_freelinkN(&(em->selected),ese);
- break;
- }
- }
+ BM_remove_selection(em->bm, data);
}
void EDBM_store_selection(BMEditMesh *em, void *data)
{
- BMEditSelection *ese;
- if(!EDBM_check_selection(em, data)){
- ese = (BMEditSelection*) MEM_callocN( sizeof(BMEditSelection), "BMEdit Selection");
- ese->type = ((BMHeader*)data)->type;
- ese->data = data;
- BLI_addtail(&(em->selected),ese);
- }
+ BM_store_selection(em->bm, data);
}
void EDBM_validate_selections(BMEditMesh *em)
{
- BMEditSelection *ese, *nextese;
-
- ese = em->selected.first;
-
- while(ese){
- nextese = ese->next;
- if (!BM_TestHFlag(ese->data, BM_SELECT)) BLI_freelinkN(&(em->selected), ese);
- ese = nextese;
- }
+ BM_validate_selections(em->bm);
}
diff --git a/source/blender/editors/mesh/bmeshutils.c b/source/blender/editors/mesh/bmeshutils.c
index e3ec1c16ce3..5e8c295d7b8 100644
--- a/source/blender/editors/mesh/bmeshutils.c
+++ b/source/blender/editors/mesh/bmeshutils.c
@@ -363,7 +363,7 @@ BMFace *EDBM_get_actFace(BMEditMesh *em, int sloppy)
BMFace *efa= NULL;
BMEditSelection *ese;
- ese = em->selected.last;
+ ese = em->bm->selected.last;
for (; ese; ese=ese->prev){
if(ese->type == BM_FACE) {
efa = (BMFace *)ese->data;
@@ -395,7 +395,7 @@ void EDBM_selectmode_flush(BMEditMesh *em)
int EDBM_get_actSelection(BMEditMesh *em, BMEditSelection *ese)
{
- BMEditSelection *ese_last = em->selected.last;
+ BMEditSelection *ese_last = em->bm->selected.last;
BMFace *efa = EDBM_get_actFace(em, 0);
ese->next = ese->prev = NULL;
diff --git a/source/blender/editors/space_view3d/drawobject.c b/source/blender/editors/space_view3d/drawobject.c
index 0c521512c12..99e68f3cf6b 100644
--- a/source/blender/editors/space_view3d/drawobject.c
+++ b/source/blender/editors/space_view3d/drawobject.c
@@ -2074,8 +2074,8 @@ static void draw_em_fancy(Scene *scene, View3D *v3d, RegionView3D *rv3d, Object
BMEdge *eed_act = NULL;
BMVert *eve_act = NULL;
- if (em->selected.last) {
- BMEditSelection *ese = em->selected.last;
+ if (em->bm->selected.last) {
+ BMEditSelection *ese = em->bm->selected.last;
/* face is handeled above */
/*if (ese->type == EDITFACE ) {
efa_act = (EditFace *)ese->data;
diff --git a/source/blender/editors/transform/transform_conversions.c b/source/blender/editors/transform/transform_conversions.c
index aeccaee070e..f8b66dbca21 100644
--- a/source/blender/editors/transform/transform_conversions.c
+++ b/source/blender/editors/transform/transform_conversions.c
@@ -2182,8 +2182,8 @@ static void createTransEditVerts(bContext *C, TransInfo *t)
if (countsel==0) return;
/* check active */
- if (em->selected.last) {
- BMEditSelection *ese = em->selected.last;
+ if (em->bm->selected.last) {
+ BMEditSelection *ese = em->bm->selected.last;
if ( ese->type == EDITVERT ) {
eve_act = (BMVert *)ese->data;
}