alt-ctrl leftmouse (e.g. current knife) now uses bmesh edge subdivide! wa-hoo! basically I had to add some slots to the subdivide operator so it could accept custom percentags for splitting edges. also put some commonly passed-around paramters into a struct, so i don't have to constantly keep changing a dozen function signatures

This commit is contained in:
Joseph Eagar
2009-02-08 17:01:28 +00:00
parent 1e3a23ee0c
commit eb7feeae77
7 changed files with 362 additions and 156 deletions

View File

@@ -62,6 +62,7 @@ void BMO_CopySlot(struct BMOperator *source_op, struct BMOperator *dest_op, int
void BMO_Set_Float(struct BMOperator *op, int slotcode, float f);
void BMO_Set_Int(struct BMOperator *op, int slotcode, int i);
void BMO_Set_PntBuf(struct BMOperator *op, int slotcode, void *p, int len);
void BMO_Set_FltBuf(BMOperator *op, int slotcode, float *p, int len);
void BMO_Set_Pnt(struct BMOperator *op, int slotcode, void *p);
void BMO_Set_Vec(struct BMOperator *op, int slotcode, float *vec);
void BMO_SetFlag(struct BMesh *bm, void *element, int flag);
@@ -161,7 +162,7 @@ enum {
BMOP_ESUBDIVIDE_CUSTOMFILL_FACES,
BMOP_ESUBDIVIDE_CUSTOMFILL_PATTERNS,
BMOP_ESUBDIVIDE_PERCENT_VERTS,
BMOP_ESUBDIVIDE_PERCENT_EDGES,
BMOP_ESUBDIVIDE_PERCENT_VALUES,
BMOP_ESUBDIVIDE_TOTSLOT,

View File

@@ -42,7 +42,7 @@ BMOpDefine def_subdop = {
BMOP_OPSLOT_PNT_BUF,
BMOP_OPSLOT_PNT_BUF,
BMOP_OPSLOT_PNT_BUF,
BMOP_OPSLOT_FLT},
BMOP_OPSLOT_FLT_BUF},
esubdivide_exec,
BMOP_ESUBDIVIDE_TOTSLOT,
0

View File

@@ -212,6 +212,15 @@ void BMO_Set_PntBuf(BMOperator *op, int slotcode, void *p, int len)
op->slots[slotcode].len = len;
}
void BMO_Set_FltBuf(BMOperator *op, int slotcode, float *p, int len)
{
if( !(op->slots[slotcode].slottype == BMOP_OPSLOT_FLT_BUF) )
return;
op->slots[slotcode].data.p = p;
op->slots[slotcode].len = len;
}
void BMO_Set_Pnt(BMOperator *op, int slotcode, void *p)
{
if( !(op->slots[slotcode].slottype == BMOP_OPSLOT_PNT) )

View File

@@ -21,6 +21,8 @@
#define SUBD_SPLIT 1
#define EDGE_PERCENT 2
/*I don't think new faces are flagged, currently, but
better safe than sorry.*/
#define FACE_NEW 2
@@ -48,12 +50,12 @@ NOTE: beauty has been renamed to flag!
*/
/* calculates offset for co, based on fractal, sphere or smooth settings */
static void alter_co(float *co, BMEdge *edge, float rad, int flag, float perc,
static void alter_co(float *co, BMEdge *edge, subdparams *params, float perc,
BMVert *vsta, BMVert *vend)
{
float vec1[3], fac;
if(flag & B_SMOOTH) {
if(params->flag & B_SMOOTH) {
/* we calculate an offset vector vec1[], to be added to *co */
float len, fac, nor[3], nor1[3], nor2[3];
@@ -77,23 +79,23 @@ static void alter_co(float *co, BMEdge *edge, float rad, int flag, float perc,
vec1[1]+= fac*nor2[1];
vec1[2]+= fac*nor2[2];
vec1[0]*= rad*len;
vec1[1]*= rad*len;
vec1[2]*= rad*len;
vec1[0]*= params->rad*len;
vec1[1]*= params->rad*len;
vec1[2]*= params->rad*len;
co[0] += vec1[0];
co[1] += vec1[1];
co[2] += vec1[2];
}
else {
if(rad > 0.0) { /* subdivide sphere */
if(params->rad > 0.0) { /* subdivide sphere */
Normalize(co);
co[0]*= rad;
co[1]*= rad;
co[2]*= rad;
co[0]*= params->rad;
co[1]*= params->rad;
co[2]*= params->rad;
}
else if(rad< 0.0) { /* fractal subdivide */
fac= rad* VecLenf(vsta->co, vend->co);
else if(params->rad< 0.0) { /* fractal subdivide */
fac= params->rad* VecLenf(vsta->co, vend->co);
vec1[0]= fac*(float)(0.5-BLI_drand());
vec1[1]= fac*(float)(0.5-BLI_drand());
vec1[2]= fac*(float)(0.5-BLI_drand());
@@ -106,18 +108,18 @@ static void alter_co(float *co, BMEdge *edge, float rad, int flag, float perc,
/* assumes in the edge is the correct interpolated vertices already */
/* percent defines the interpolation, rad and flag are for special options */
/* results in new vertex with correct coordinate, vertex normal and weight group info */
static BMVert *bm_subdivide_edge_addvert(BMesh *bm, BMEdge *edge, float rad,
int flag, float percent, BMEdge **out,
BMVert *vsta, BMVert *vend)
static BMVert *bm_subdivide_edge_addvert(BMesh *bm, BMEdge *edge,
subdparams *params, float percent,
BMEdge **out,BMVert *vsta,BMVert *vend)
{
BMVert *ev;
// float co[3];
ev = BM_Split_Edge(bm, edge->v1, edge, out, percent, 1);
if (flag & SELTYPE_INNER) BM_Select_Vert(bm, ev, 1);
if (params->flag & SELTYPE_INNER) BM_Select_Vert(bm, ev, 1);
/* offset for smooth or sphere or fractal */
alter_co(ev->co, edge, rad, flag, percent, vsta, vend);
alter_co(ev->co, edge, params, percent, vsta, vend);
#if 0 //TODO
/* clip if needed by mirror modifier */
@@ -138,48 +140,33 @@ static BMVert *bm_subdivide_edge_addvert(BMesh *bm, BMEdge *edge, float rad,
}
static BMVert *subdivideedgenum(BMesh *bm, BMEdge *edge,
int curpoint, int totpoint, float rad,
int flag, BMEdge **newe,
BMVert *vsta, BMVert *vend)
int curpoint, int totpoint, subdparams *params,
BMEdge **newe, BMVert *vsta, BMVert *vend)
{
BMVert *ev;
float percent;
if (flag & (B_PERCENTSUBD) && totpoint == 1)
/*I guess the idea is vertices store what
percent to use?*/
//percent=(float)(edge->tmp.l)/32768.0f;
percent= 1.0; //edge->tmp.fp;
if (BMO_TestFlag(bm, edge, EDGE_PERCENT) && totpoint == 1)
percent= *((float*)BLI_ghash_lookup(params->percenthash,edge));
else {
percent= 1.0f/(float)(totpoint+1-curpoint);
}
/*{
float co[3], co2[3];
VecSubf(co, edge->v2->co, edge->v1->co);
VecMulf(co, 1.0f/(float)(totpoint+1-curpoint));
VecAddf(co2, edge->v1->co, co);
*/
ev= bm_subdivide_edge_addvert(bm, edge, rad, flag, percent,
newe, vsta, vend);
/* VECCOPY(ev->co, co2);
}
*/
ev= bm_subdivide_edge_addvert(bm, edge, params, percent,
newe, vsta, vend);
return ev;
}
static void bm_subdivide_multicut(BMesh *bm, BMEdge *edge, float rad,
int flag, int numcuts,
static void bm_subdivide_multicut(BMesh *bm, BMEdge *edge, subdparams *params,
BMVert *vsta, BMVert *vend) {
BMEdge *eed = edge, *newe;
BMVert *v;
int i;
int i, numcuts = params->numcuts;
for(i=0;i<numcuts;i++) {
v = subdivideedgenum(bm, eed, i, numcuts, rad,
flag, &newe, vsta, vend);
v = subdivideedgenum(bm, eed, i, params->numcuts, params,
&newe, vsta, vend);
BMO_SetFlag(bm, v, SUBD_SPLIT);
BMO_SetFlag(bm, eed, SUBD_SPLIT);
}
@@ -199,28 +186,28 @@ v3---------v2
v4---v0---v1
*/
static void q_1edge_split(BMesh *bm, BMFace *face, BMVert **vlist, int numcuts,
int flag, float rad) {
static void q_1edge_split(BMesh *bm, BMFace *face,
BMVert **verts, subdparams *params) {
BMFace *nf;
int i, add;
int i, add, numcuts = params->numcuts;
/*if it's odd, the middle face is a quad, otherwise it's a triangle*/
if (numcuts % 2==0) {
add = 2;
for (i=0; i<numcuts; i++) {
if (i == numcuts/2) add -= 1;
BM_Connect_Verts(bm, vlist[i], vlist[numcuts+add],
BM_Connect_Verts(bm, verts[i], verts[numcuts+add],
&nf);
}
} else {
add = 2;
for (i=0; i<numcuts; i++) {
BM_Connect_Verts(bm, vlist[i], vlist[numcuts+add],
BM_Connect_Verts(bm, verts[i], verts[numcuts+add],
&nf);
if (i == numcuts/2) {
add -= 1;
BM_Connect_Verts(bm, vlist[i],
vlist[numcuts+add],
BM_Connect_Verts(bm, verts[i],
verts[numcuts+add],
&nf);
}
}
@@ -246,13 +233,14 @@ v5---v0---v1
*/
static void q_2edge_op_split(BMesh *bm, BMFace *face, BMVert **vlist,
int numcuts, int flag, float rad) {
static void q_2edge_op_split(BMesh *bm, BMFace *face, BMVert **verts,
subdparams *params)
{
BMFace *nf;
int i;
int i, numcuts = params->numcuts;
for (i=0; i<numcuts; i++) {
BM_Connect_Verts(bm, vlist[i],vlist[(numcuts-i-1)+numcuts+2],
BM_Connect_Verts(bm, verts[i],verts[(numcuts-i-1)+numcuts+2],
&nf);
}
}
@@ -272,16 +260,17 @@ v6--------v5
v7-v0--v1-v2
*/
static void q_2edge_split(BMesh *bm, BMFace *face, BMVert **vlist,
int numcuts, int flag, float rad) {
static void q_2edge_split(BMesh *bm, BMFace *face, BMVert **verts,
subdparams *params)
{
BMFace *nf;
int i;
int i, numcuts = params->numcuts;
for (i=0; i<numcuts; i++) {
BM_Connect_Verts(bm, vlist[i], vlist[numcuts+(numcuts-i)],
BM_Connect_Verts(bm, verts[i], verts[numcuts+(numcuts-i)],
&nf);
}
BM_Connect_Verts(bm, vlist[numcuts*2+3], vlist[numcuts*2+1], &nf);
BM_Connect_Verts(bm, verts[numcuts*2+3], verts[numcuts*2+1], &nf);
}
subdpattern q_2edge = {
@@ -300,25 +289,26 @@ v8--v7--v6-v5
v9-v0--v1-v2
*/
static void q_3edge_split(BMesh *bm, BMFace *face, BMVert **vlist,
int numcuts, int flag, float rad) {
static void q_3edge_split(BMesh *bm, BMFace *face, BMVert **verts,
subdparams *params)
{
BMFace *nf;
int i, add=0;
int i, add=0, numcuts = params->numcuts;
for (i=0; i<numcuts; i++) {
if (i == numcuts/2) {
if (numcuts % 2 != 0) {
BM_Connect_Verts(bm, vlist[numcuts-i-1+add],
vlist[i+numcuts+1], &nf);
BM_Connect_Verts(bm, verts[numcuts-i-1+add],
verts[i+numcuts+1], &nf);
}
add = numcuts*2+2;
}
BM_Connect_Verts(bm, vlist[numcuts-i-1+add],
vlist[i+numcuts+1], &nf);
BM_Connect_Verts(bm, verts[numcuts-i-1+add],
verts[i+numcuts+1], &nf);
}
for (i=0; i<numcuts/2+1; i++) {
BM_Connect_Verts(bm, vlist[i],vlist[(numcuts-i)+numcuts*2+1],
BM_Connect_Verts(bm, verts[i],verts[(numcuts-i)+numcuts*2+1],
&nf);
}
}
@@ -340,27 +330,30 @@ first line | | last line
it goes from bottom up
*/
static void q_4edge_split(BMesh *bm, BMFace *face, BMVert **vlist, int numcuts,
int flag, float rad) {
static void q_4edge_split(BMesh *bm, BMFace *face, BMVert **verts,
subdparams *params)
{
BMFace *nf;
BMVert *v, *v1, *v2;
BMEdge *e, *ne;
BMVert **lines = MEM_callocN(sizeof(BMVert*)*(numcuts+2)*(numcuts+2),
"q_4edge_split");
BMVert **lines;
int numcuts = params->numcuts;
int i, j, a, b, s=numcuts+2, totv=numcuts*4+4;
lines = MEM_callocN(sizeof(BMVert*)*(numcuts+2)*(numcuts+2),
"q_4edge_split");
/*build a 2-dimensional array of verts,
containing every vert (and all new ones)
in the face.*/
/*first line*/
for (i=0; i<numcuts+2; i++) {
lines[i] = vlist[numcuts*3+2+(numcuts-i+1)];
lines[i] = verts[numcuts*3+2+(numcuts-i+1)];
}
/*last line*/
for (i=0; i<numcuts+2; i++) {
lines[(s-1)*s+i] = vlist[numcuts+i];
lines[(s-1)*s+i] = verts[numcuts+i];
}
/*first and last members of middle lines*/
@@ -368,19 +361,19 @@ static void q_4edge_split(BMesh *bm, BMFace *face, BMVert **vlist, int numcuts,
a = i;
b = numcuts + 1 + numcuts + 1 + (numcuts - i - 1);
e = BM_Connect_Verts(bm, vlist[a], vlist[b], &nf);
if (flag & SELTYPE_INNER) {
e = BM_Connect_Verts(bm, verts[a], verts[b], &nf);
if (params->flag & SELTYPE_INNER) {
BM_Select_Edge(bm, e, 1);
BM_Select_Face(bm, nf, 1);
}
v1 = lines[(i+1)*s] = vlist[a];
v2 = lines[(i+1)*s + s-1] = vlist[b];
v1 = lines[(i+1)*s] = verts[a];
v2 = lines[(i+1)*s + s-1] = verts[b];
for (a=0; a<numcuts; a++) {
v = subdivideedgenum(bm, e, a, numcuts, rad, flag, &ne,
v = subdivideedgenum(bm, e, a, numcuts, params, &ne,
v1, v2);
if (flag & SELTYPE_INNER) {
if (params->flag & SELTYPE_INNER) {
BM_Select_Edge(bm, ne, 1);
}
lines[(i+1)*s+a+1] = v;
@@ -392,7 +385,7 @@ static void q_4edge_split(BMesh *bm, BMFace *face, BMVert **vlist, int numcuts,
a = i*s + j;
b = (i-1)*s + j;
e = BM_Connect_Verts(bm, lines[a], lines[b], &nf);
if (flag & SELTYPE_INNER) {
if (params->flag & SELTYPE_INNER) {
BM_Select_Edge(bm, e, 1);
BM_Select_Face(bm, nf, 1);
}
@@ -411,13 +404,14 @@ static void q_4edge_split(BMesh *bm, BMFace *face, BMVert **vlist, int numcuts,
v4--v0--v1--v2
s s
*/
static void t_1edge_split(BMesh *bm, BMFace *face, BMVert **vlist,
int numcuts, int flag, float rad) {
static void t_1edge_split(BMesh *bm, BMFace *face, BMVert **verts,
subdparams *params)
{
BMFace *nf;
int i;
int i, numcuts = params->numcuts;
for (i=0; i<numcuts; i++) {
BM_Connect_Verts(bm, vlist[i], vlist[numcuts+1], &nf);
BM_Connect_Verts(bm, verts[i], verts[numcuts+1], &nf);
}
}
@@ -436,13 +430,14 @@ subdpattern t_1edge = {
v6--v0--v1--v2
s s
*/
static void t_2edge_split(BMesh *bm, BMFace *face, BMVert **vlist,
int numcuts, int flag, float rad) {
static void t_2edge_split(BMesh *bm, BMFace *face, BMVert **verts,
subdparams *params)
{
BMFace *nf;
int i;
int i, numcuts = params->numcuts;
for (i=0; i<numcuts; i++) {
BM_Connect_Verts(bm, vlist[i], vlist[numcuts+numcuts-i], &nf);
BM_Connect_Verts(bm, verts[i], verts[numcuts+numcuts-i], &nf);
}
}
@@ -462,49 +457,50 @@ sv7/---v---\ v3 s
v8--v0--v1--v2
s s
*/
static void t_3edge_split(BMesh *bm, BMFace *face, BMVert **vlist,
int numcuts, int flag, float rad) {
static void t_3edge_split(BMesh *bm, BMFace *face, BMVert **verts,
subdparams *params)
{
BMFace *nf;
BMEdge *e, *ne;
BMVert ***lines, *v;
void *stackarr[1];
int i, j, a, b;
int i, j, a, b, numcuts = params->numcuts;
/*number of verts in each line*/
lines = MEM_callocN(sizeof(void*)*(numcuts+2), "triangle vert table");
lines[0] = (BMVert**) stackarr;
lines[0][0] = vlist[numcuts*2+1];
lines[0][0] = verts[numcuts*2+1];
lines[1+numcuts] = MEM_callocN(sizeof(void*)*(numcuts+2),
"triangle vert table 2");
for (i=0; i<numcuts; i++) {
lines[1+numcuts][1+i] = vlist[i];
lines[1+numcuts][1+i] = verts[i];
}
lines[1+numcuts][0] = vlist[numcuts*3+2];
lines[1+numcuts][1+numcuts] = vlist[numcuts];
lines[1+numcuts][0] = verts[numcuts*3+2];
lines[1+numcuts][1+numcuts] = verts[numcuts];
for (i=0; i<numcuts; i++) {
lines[i+1] = MEM_callocN(sizeof(void*)*(2+i),
"triangle vert table row");
a = numcuts*2 + 2 + i;
b = numcuts + numcuts - i;
e = BM_Connect_Verts(bm, vlist[a], vlist[b], &nf);
e = BM_Connect_Verts(bm, verts[a], verts[b], &nf);
if (flag & SELTYPE_INNER) {
if (params->flag & SELTYPE_INNER) {
BM_Select_Edge(bm, e, 1);
BM_Select_Face(bm, nf, 1);
}
lines[i+1][0] = vlist[a];
lines[i+1][1+i] = vlist[b];
lines[i+1][0] = verts[a];
lines[i+1][1+i] = verts[b];
for (j=0; j<i; j++) {
v = subdivideedgenum(bm, e, j, i, rad, flag, &ne,
vlist[a], vlist[b]);
v = subdivideedgenum(bm, e, j, i, params, &ne,
verts[a], verts[b]);
lines[i+1][j+1] = v;
if (flag & SELTYPE_INNER) {
if (params->flag & SELTYPE_INNER) {
BM_Select_Edge(bm, ne, 1);
}
}
@@ -524,14 +520,14 @@ sv7/---v---\ v3 s
for (j=0; j<i; j++) {
e= BM_Connect_Verts(bm, lines[i][j], lines[i+1][j+1],
&nf);
if (flag & SELTYPE_INNER) {
if (params->flag & SELTYPE_INNER) {
BM_Select_Edge(bm, e, 1);
BM_Select_Face(bm, nf, 1);
}
e= BM_Connect_Verts(bm,lines[i][j+1],lines[i+1][j+1],
&nf);
if (flag & SELTYPE_INNER) {
if (params->flag & SELTYPE_INNER) {
BM_Select_Edge(bm, e, 1);
BM_Select_Face(bm, nf, 1);
}
@@ -577,20 +573,21 @@ typedef struct subd_facedata {
void esubdivide_exec(BMesh *bmesh, BMOperator *op)
{
V_DECLARE(facedata);
V_DECLARE(verts);
V_DECLARE(edges);
BMOpSlot *einput, *finput, *pinput;
BMEdge *edge, **edges = NULL;
V_DECLARE(edges);
BMFace *face;
BMLoop *nl;
BMVert **verts = NULL;
V_DECLARE(verts);
BMIter fiter, liter;
GHash *customfill_hash;
GHash *customfill_hash, *percent_hash;
subdpattern *pat;
subdparams params;
subd_facedata *facedata = NULL;
V_DECLARE(facedata);
float rad;
int i, j, matched, a, b, numcuts, flag, selaction, fillindex;
int i, j, matched, a, b, numcuts, flag, selaction;
BMO_Flag_Buffer(bmesh, op, BMOP_ESUBDIVIDE_EDGES, SUBD_SPLIT);
@@ -602,8 +599,7 @@ void esubdivide_exec(BMesh *bmesh, BMOperator *op)
if (selaction == SUBDIV_SELECT_INNER) flag |= SELTYPE_INNER;
einput = BMO_GetSlot(op, BMOP_ESUBDIVIDE_EDGES);
/*first go through and split edges*/
/*first go through and tag edges*/
for (i=0; i<einput->len; i++) {
edge = ((BMEdge**)einput->data.p)[i];
BMO_SetFlag(bmesh, edge, SUBD_SPLIT);
@@ -611,7 +607,9 @@ void esubdivide_exec(BMesh *bmesh, BMOperator *op)
customfill_hash = BLI_ghash_new(BLI_ghashutil_ptrhash,
BLI_ghashutil_ptrcmp);
percent_hash = BLI_ghash_new(BLI_ghashutil_ptrhash,
BLI_ghashutil_ptrcmp);
/*process custom fill patterns*/
finput = BMO_GetSlot(op, BMOP_ESUBDIVIDE_CUSTOMFILL_FACES);
pinput = BMO_GetSlot(op, BMOP_ESUBDIVIDE_CUSTOMFILL_PATTERNS);
@@ -622,6 +620,20 @@ void esubdivide_exec(BMesh *bmesh, BMOperator *op)
((void**)pinput->data.p)[i]);
}
einput = BMO_GetSlot(op, BMOP_ESUBDIVIDE_PERCENT_EDGES);
pinput = BMO_GetSlot(op, BMOP_ESUBDIVIDE_PERCENT_VALUES);
for (i=0; i<einput->len; i++) {
edge = ((BMEdge**)einput->data.p)[i];
BMO_SetFlag(bmesh, edge, EDGE_PERCENT);
BLI_ghash_insert(percent_hash, edge, ((float*)pinput->data.p)+i);
}
params.flag = flag;
params.numcuts = numcuts;
params.percenthash = percent_hash;
params.rad = rad;
for (face=BMIter_New(&fiter, bmesh, BM_FACES, NULL);
face; face=BMIter_Step(&fiter)) {
/*figure out which pattern to use*/
@@ -694,11 +706,12 @@ void esubdivide_exec(BMesh *bmesh, BMOperator *op)
}
}
einput = BMO_GetSlot(op, BMOP_ESUBDIVIDE_EDGES);
/*go through and split edges*/
for (i=0; i<einput->len; i++) {
edge = ((BMEdge**)einput->data.p)[i];
bm_subdivide_multicut(bmesh, edge, rad, flag, numcuts,
edge->v1, edge->v2);
bm_subdivide_multicut(bmesh, edge,&params, edge->v1, edge->v2);
//BM_Split_Edge_Multi(bmesh, edge, numcuts);
}
@@ -737,7 +750,7 @@ void esubdivide_exec(BMesh *bmesh, BMOperator *op)
j += 1;
}
pat->connectexec(bmesh, face, verts, numcuts, flag, rad);
pat->connectexec(bmesh, face, verts, &params);
i++;
}

View File

@@ -7,9 +7,12 @@
#include "BLI_arithb.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define EDGE_NEW 1
#define FACE_NEW 1
void triangulate_exec(BMesh *bmesh, BMOperator *op)
{
BMOpSlot *finput;

View File

@@ -76,6 +76,7 @@ editmesh_loop: tools with own drawing subloops, select, knife, subdiv
#include "ED_view3d.h"
#include "mesh_intern.h"
#include "bmesh.h"
/* **** XXX ******** */
static void BIF_undo_push() {}
@@ -204,8 +205,8 @@ void CutEdgeloop(Object *obedit, EditMesh *em, int numcuts)
EditEdge *nearest=NULL, *eed;
float fac;
int keys = 0, holdnum=0, selectmode, dist;
short mvalo[2] = {0,0}, mval[2];
short event, val, choosing=1, cancel=0, cuthalf = 0, smooth=0;
short mvalo[2] = {0,0}, mval[2] = {0, 0};
short event=0, val, choosing=1, cancel=0, cuthalf = 0, smooth=0;
short hasHidden = 0;
char msg[128];
@@ -473,7 +474,7 @@ static float seg_intersect(EditEdge *e, CutCurve *c, int len, char mode, struct
float m1, b1, m2, b2, x21, x22, y21, y22, xi;
float yi, x1min, x1max, y1max, y1min, perc=0;
float *scr;
float threshold;
float threshold = 0.0;
int i;
//threshold = 0.000001; /*tolerance for vertex intersection*/
@@ -619,20 +620,181 @@ static float seg_intersect(EditEdge *e, CutCurve *c, int len, char mode, struct
}
static float bm_seg_intersect(BMEdge *e, CutCurve *c, int len, char mode,
struct GHash *gh, int *isected)
{
#define MAXSLOPE 100000
float x11, y11, x12=0, y12=0, x2max, x2min, y2max;
float y2min, dist, lastdist=0, xdiff2, xdiff1;
float m1, b1, m2, b2, x21, x22, y21, y22, xi;
float yi, x1min, x1max, y1max, y1min, perc=0;
float *scr;
float threshold = 0.0;
int i;
//threshold = 0.000001; /*tolerance for vertex intersection*/
// XXX threshold = scene->toolsettings->select_thresh / 100;
/* Get screen coords of verts */
scr = BLI_ghash_lookup(gh, e->v1);
x21=scr[0];
y21=scr[1];
scr = BLI_ghash_lookup(gh, e->v2);
x22=scr[0];
y22=scr[1];
xdiff2=(x22-x21);
if (xdiff2) {
m2=(y22-y21)/xdiff2;
b2= ((x22*y21)-(x21*y22))/xdiff2;
}
else {
m2=MAXSLOPE; /* Verticle slope */
b2=x22;
}
*isected = 0;
/*check for *exact* vertex intersection first*/
if(mode!=KNIFE_MULTICUT){
for (i=0; i<len; i++){
if (i>0){
x11=x12;
y11=y12;
}
else {
x11=c[i].x;
y11=c[i].y;
}
x12=c[i].x;
y12=c[i].y;
/*test e->v1*/
if((x11 == x21 && y11 == y21) || (x12 == x21 && y12 == y21)){
perc = 0;
*isected = 1;
return(perc);
}
/*test e->v2*/
else if((x11 == x22 && y11 == y22) || (x12 == x22 && y12 == y22)){
perc = 0;
*isected = 2;
return(perc);
}
}
}
/*now check for edge interesect (may produce vertex intersection as well)*/
for (i=0; i<len; i++){
if (i>0){
x11=x12;
y11=y12;
}
else {
x11=c[i].x;
y11=c[i].y;
}
x12=c[i].x;
y12=c[i].y;
/* Perp. Distance from point to line */
if (m2!=MAXSLOPE) dist=(y12-m2*x12-b2);/* /sqrt(m2*m2+1); Only looking for */
/* change in sign. Skip extra math */
else dist=x22-x12;
if (i==0) lastdist=dist;
/* if dist changes sign, and intersect point in edge's Bound Box*/
if ((lastdist*dist)<=0){
xdiff1=(x12-x11); /* Equation of line between last 2 points */
if (xdiff1){
m1=(y12-y11)/xdiff1;
b1= ((x12*y11)-(x11*y12))/xdiff1;
}
else{
m1=MAXSLOPE;
b1=x12;
}
x2max=MAX2(x21,x22)+0.001; /* prevent missed edges */
x2min=MIN2(x21,x22)-0.001; /* due to round off error */
y2max=MAX2(y21,y22)+0.001;
y2min=MIN2(y21,y22)-0.001;
/* Found an intersect, calc intersect point */
if (m1==m2){ /* co-incident lines */
/* cut at 50% of overlap area*/
x1max=MAX2(x11, x12);
x1min=MIN2(x11, x12);
xi= (MIN2(x2max,x1max)+MAX2(x2min,x1min))/2.0;
y1max=MAX2(y11, y12);
y1min=MIN2(y11, y12);
yi= (MIN2(y2max,y1max)+MAX2(y2min,y1min))/2.0;
}
else if (m2==MAXSLOPE){
xi=x22;
yi=m1*x22+b1;
}
else if (m1==MAXSLOPE){
xi=x12;
yi=m2*x12+b2;
}
else {
xi=(b1-b2)/(m2-m1);
yi=(b1*m2-m1*b2)/(m2-m1);
}
/* Intersect inside bounding box of edge?*/
if ((xi>=x2min)&&(xi<=x2max)&&(yi<=y2max)&&(yi>=y2min)){
/*test for vertex intersect that may be 'close enough'*/
if(mode!=KNIFE_MULTICUT){
if(xi <= (x21 + threshold) && xi >= (x21 - threshold)){
if(yi <= (y21 + threshold) && yi >= (y21 - threshold)){
*isected = 1;
perc = 0;
break;
}
}
if(xi <= (x22 + threshold) && xi >= (x22 - threshold)){
if(yi <= (y22 + threshold) && yi >= (y22 - threshold)){
*isected = 2;
perc = 0;
break;
}
}
}
if ((m2<=1.0)&&(m2>=-1.0)) perc = (xi-x21)/(x22-x21);
else perc=(yi-y21)/(y22-y21); /*lower slope more accurate*/
//isect=32768.0*(perc+0.0000153); /* Percentage in 1/32768ths */
break;
}
}
lastdist=dist;
}
return(perc);
}
#define MAX_CUTS 256
static int knife_cut_exec(bContext *C, wmOperator *op)
{
Object *obedit= CTX_data_edit_object(C);
EditMesh *em= ((Mesh *)obedit->data)->edit_mesh;
EditMesh *em= ((Mesh *)obedit->data)->edit_mesh, *em2;
BMesh *bm;
ARegion *ar= CTX_wm_region(C);
EditEdge *eed;
EditVert *eve;
BMVert *bv;
BMIter iter;
BMEdge **edges = NULL, *be;
V_DECLARE(edges);
BMOperator bmop;
CutCurve curve[MAX_CUTS];
struct GHash *gh;
float isect=0.0;
float *scr, co[4];
int len=0;
float *scr, co[4], *percents = NULL;
V_DECLARE(percents);
int len=0, isected, flag;
short numcuts=1, mode= RNA_int_get(op->ptr, "type");
if (EM_nvertices_selected(em) < 2) {
@@ -651,51 +813,67 @@ static int knife_cut_exec(bContext *C, wmOperator *op)
if(len<2) return OPERATOR_CANCELLED;
/*store percentage of edge cut for KNIFE_EXACT here.*/
for(eed=em->edges.first; eed; eed= eed->next)
eed->tmp.fp = 0.0;
bm = editmesh_to_bmesh(em);
/*the floating point coordinates of verts in screen space will be stored in a hash table according to the vertices pointer*/
gh = BLI_ghash_new(BLI_ghashutil_ptrhash, BLI_ghashutil_ptrcmp);
for(eve=em->verts.first; eve; eve=eve->next){
for(bv=BMIter_New(&iter, bm, BM_VERTS, NULL);bv;bv=BMIter_Step(&iter)){
scr = MEM_mallocN(sizeof(float)*2, "Vertex Screen Coordinates");
VECCOPY(co, eve->co);
VECCOPY(co, bv->co);
co[3]= 1.0;
Mat4MulVec4fl(obedit->obmat, co);
project_float(ar, co, scr);
BLI_ghash_insert(gh, eve, scr);
eve->f1 = 0; /*store vertex intersection flag here*/
BLI_ghash_insert(gh, bv, scr);
}
eed= em->edges.first;
while(eed) {
if( eed->v1->f & eed->v2->f & SELECT ){ // NOTE: uses vertex select, subdiv doesnt do edges yet
isect= seg_intersect(eed, curve, len, mode, gh);
if (isect!=0.0f) eed->f2= 1;
else eed->f2=0;
eed->tmp.fp= isect;
//printf("isect=%i\n", isect);
/*store percentage of edge cut for KNIFE_EXACT here.*/
for (be=BMIter_New(&iter, bm, BM_EDGES, NULL); be; be=BMIter_Step(&iter)) {
if( BM_Is_Selected(bm, be) ) {
isect= bm_seg_intersect(be, curve, len, mode, gh, &isected);
if (isect != 0.0f) {
V_GROW(edges);
V_GROW(percents);
edges[V_COUNT(edges)-1] = be;
percents[V_COUNT(percents)-1] = isect;
}
}
else {
eed->f2=0;
eed->f1=0;
}
eed= eed->next;
}
BMO_Init_Op(&bmop, BMOP_ESUBDIVIDE);
if (mode==KNIFE_MIDPOINT) esubdivideflag(obedit, em, SELECT, 0, B_KNIFE, 1, SUBDIV_SELECT_ORIG);
else if (mode==KNIFE_MULTICUT) esubdivideflag(obedit, em, SELECT, 0, B_KNIFE, numcuts, SUBDIV_SELECT_ORIG);
else esubdivideflag(obedit, em, SELECT, 0, B_KNIFE|B_PERCENTSUBD, 1, SUBDIV_SELECT_ORIG);
BMO_Set_Int(&bmop, BMOP_ESUBDIVIDE_NUMCUTS, numcuts);
flag = B_KNIFE;
if (mode == KNIFE_MIDPOINT) numcuts = 1;
else if (mode != KNIFE_MULTICUT) {
BMO_Set_PntBuf(&bmop, BMOP_ESUBDIVIDE_PERCENT_EDGES, edges, V_COUNT(edges));
BMO_Set_FltBuf(&bmop, BMOP_ESUBDIVIDE_PERCENT_VALUES, percents, V_COUNT(percents));
}
eed=em->edges.first;
while(eed){
eed->f2=0;
eed->f1=0;
eed=eed->next;
}
BMO_Set_Int(&bmop, BMOP_ESUBDIVIDE_FLAG, flag);
BMO_Set_Float(&bmop, BMOP_ESUBDIVIDE_RADIUS, 0);
BMO_Set_Int(&bmop, BMOP_ESUBDIVIDE_SELACTION, SUBDIV_SELECT_ORIG);
BMO_Set_PntBuf(&bmop, BMOP_ESUBDIVIDE_EDGES, edges, V_COUNT(edges));
BMO_Exec_Op(bm, &bmop);
BMO_Finish_Op(bm, &bmop);
V_FREE(edges);
V_FREE(percents);
//if (mode==KNIFE_MIDPOINT) esubdivideflag(obedit, em, SELECT, 0, B_KNIFE, 1, SUBDIV_SELECT_ORIG);
//else if (mode==KNIFE_MULTICUT) esubdivideflag(obedit, em, SELECT, 0, B_KNIFE, numcuts, SUBDIV_SELECT_ORIG);
//else esubdivideflag(obedit, em, SELECT, 0, B_KNIFE|B_PERCENTSUBD, 1, SUBDIV_SELECT_ORIG);
BLI_ghash_free(gh, NULL, (GHashValFreeFP)MEM_freeN);
free_editMesh(em);
em2 = bmesh_to_editmesh(bm);
*em = *em2;
MEM_freeN(em2);
BM_Free_Mesh(bm);
return OPERATOR_FINISHED;
}

View File

@@ -176,6 +176,8 @@ void ED_operatortypes_mesh(void)
WM_operatortype_append(MESH_OT_smooth_vertex);
WM_operatortype_append(MESH_OT_flip_editnormals);
WM_operatortype_append(MESH_OT_knife_cut);
WM_operatortype_append(MESH_OT_bmesh_test);
}
@@ -285,7 +287,7 @@ void ED_keymap_mesh(wmWindowManager *wm)
WM_keymap_add_item(keymap, "MESH_OT_knife_cut", LEFTMOUSE, KM_PRESS, KM_ALT|KM_CTRL, 0);
WM_keymap_add_item(keymap, "MESH_OT_bmesh_test", JKEY, KM_PRESS, 0, 0);
}