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.

This commit is contained in:
Joseph Eagar
2009-07-17 10:54:00 +00:00
parent 359fb502b6
commit f2138686d9
14 changed files with 415 additions and 206 deletions

View File

@@ -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;

View File

@@ -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;

View File

@@ -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

View File

@@ -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);

View File

@@ -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);
}
}
/* 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;
}
}

View File

@@ -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,

View File

@@ -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);

View File

@@ -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*/

View File

@@ -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);

View File

@@ -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;
}
}

View File

@@ -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);
}

View File

@@ -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;

View File

@@ -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;

View File

@@ -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;
}