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:
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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*/
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user