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
diff options
context:
space:
mode:
authorJohnny Matthews <johnny.matthews@gmail.com>2005-07-13 19:20:40 +0400
committerJohnny Matthews <johnny.matthews@gmail.com>2005-07-13 19:20:40 +0400
commit798d39dd4cc3c1cfeca33d7ebe99ca2c0e41ba99 (patch)
treed450e59eee443c77670b2306531c19eac1035b75
parent6a648da13f8d1c71ea2450e5e8bc969712316172 (diff)
Well here it is. Subdivision/Loop Tools Recode Commit #1
Ton has been pushing me to get this in and finish it up with help, so here is a run down of the commit Revised Features Subdivide now is Edge based, allows for multicut Loopcut was recoded, now has multi option Knife tool now has multi option New Features Edgeslide Edgering select Removed Features Alt-B Edgeloop selection (use alt-RMB in edgemode) Shift-R Faceloop selection (use alt-RMB in facemode) Old Subdivide (Except for smooth which is left in until new one works) Todo Subdivide Smooth Math is broken - could use some help here (look for alter_co in editmesh_tools.c) Tweak mouse control of Edgeslide is hackish ATM Add Non-proportional movement to edgeslide Add smooth option to new loopcut I probably left something out. See here for more info http://wiki.blender.org/bin/view.pl/Blenderdev/EdgeSubdivision
-rw-r--r--source/blender/blenlib/BLI_linklist.h1
-rw-r--r--source/blender/blenlib/intern/BLI_linklist.c17
-rw-r--r--source/blender/include/BIF_editmesh.h9
-rw-r--r--source/blender/src/buttons_editing.c4
-rw-r--r--source/blender/src/editmesh_add.c22
-rw-r--r--source/blender/src/editmesh_loop.c1547
-rw-r--r--source/blender/src/editmesh_mods.c88
-rw-r--r--source/blender/src/editmesh_tools.c3122
-rw-r--r--source/blender/src/editobject.c48
-rw-r--r--source/blender/src/header_view3d.c24
-rw-r--r--source/blender/src/space.c13
-rw-r--r--source/blender/src/toolbox.c5
12 files changed, 2693 insertions, 2207 deletions
diff --git a/source/blender/blenlib/BLI_linklist.h b/source/blender/blenlib/BLI_linklist.h
index d0e6effae3d..2e75420a1ff 100644
--- a/source/blender/blenlib/BLI_linklist.h
+++ b/source/blender/blenlib/BLI_linklist.h
@@ -52,6 +52,7 @@ int BLI_linklist_length (struct LinkNode *list);
void BLI_linklist_reverse (struct LinkNode **listp);
void BLI_linklist_prepend (struct LinkNode **listp, void *ptr);
+void BLI_linklist_append (struct LinkNode **listp, void *ptr);
void BLI_linklist_prepend_arena (struct LinkNode **listp, void *ptr, struct MemArena *ma);
void BLI_linklist_free (struct LinkNode *list, LinkNodeFreeFP freefunc);
diff --git a/source/blender/blenlib/intern/BLI_linklist.c b/source/blender/blenlib/intern/BLI_linklist.c
index ad945b53d11..253d127db38 100644
--- a/source/blender/blenlib/intern/BLI_linklist.c
+++ b/source/blender/blenlib/intern/BLI_linklist.c
@@ -76,6 +76,23 @@ void BLI_linklist_prepend(LinkNode **listp, void *ptr) {
*listp= nlink;
}
+void BLI_linklist_append(LinkNode **listp, void *ptr) {
+ LinkNode *nlink= MEM_mallocN(sizeof(*nlink), "nlink");
+ LinkNode *node = *listp;
+
+ nlink->link = ptr;
+ nlink->next = NULL;
+
+ if(node == NULL){
+ *listp = nlink;
+ } else {
+ while(node->next != NULL){
+ node = node->next;
+ }
+ node->next = nlink;
+ }
+}
+
void BLI_linklist_prepend_arena(LinkNode **listp, void *ptr, MemArena *ma) {
LinkNode *nlink= BLI_memarena_alloc(ma, sizeof(*nlink));
nlink->link= ptr;
diff --git a/source/blender/include/BIF_editmesh.h b/source/blender/include/BIF_editmesh.h
index 0f794e89ed6..c1dd2c43afa 100644
--- a/source/blender/include/BIF_editmesh.h
+++ b/source/blender/include/BIF_editmesh.h
@@ -101,6 +101,7 @@ extern void EM_free_backbuf_border(void);
extern void EM_selectmode_menu(void);
+
extern void vertexnoise(void);
extern void vertexsmooth(void);
extern void righthandfaces(int select);
@@ -135,20 +136,22 @@ extern void editmesh_deselect_by_material(int index);
extern void Edge_Menu(void);
extern void editmesh_mark_seam(int clear);
+
/* ******************* editmesh_loop.c */
#define KNIFE_PROMPT 0
#define KNIFE_EXACT 1
#define KNIFE_MIDPOINT 2
+#define KNIFE_MULTICUT 3
+extern void CutEdgeloop(int numcuts);
extern void KnifeSubdivide(char mode);
extern void LoopMenu(void);
#define LOOP_SELECT 1
#define LOOP_CUT 2
-extern void loopoperations(char mode);
-extern void vertex_loop_select(void);
+extern short sharesFace(struct EditEdge* e1, struct EditEdge* e2);
/* ******************* editmesh_tools.c */
extern void convert_to_triface(int all);
@@ -156,6 +159,7 @@ extern int removedoublesflag(short flag, float limit);
extern void xsortvert_flag(int flag);
extern void hashvert_flag(int flag);
extern void subdivideflag(int flag, float rad, int beauty);
+extern void esubdivideflag(int flag, float rad, int beauty, int numcuts, int selecttype);
extern void extrude_mesh(void);
extern void split_mesh(void);
extern void extrude_repeat_mesh(int steps, float offs);
@@ -168,6 +172,7 @@ extern void edge_flip(void);
extern void fill_mesh(void);
extern void bevel_menu();
void edge_rotate_selected(int dir);
+void EdgeSlide(short immediate, float imperc);
#endif
diff --git a/source/blender/src/buttons_editing.c b/source/blender/src/buttons_editing.c
index e07b0d2118b..8a8423fe4bc 100644
--- a/source/blender/src/buttons_editing.c
+++ b/source/blender/src/buttons_editing.c
@@ -2048,7 +2048,7 @@ void do_meshbuts(unsigned short event)
break;
case B_SUBDIV:
waitcursor(1);
- subdivideflag(1, 0.0, editbutflag & B_BEAUTY);
+ esubdivideflag(1, 0.0, editbutflag & B_BEAUTY,1,0);
countall();
waitcursor(0);
allqueue(REDRAWVIEW3D, 0);
@@ -2059,7 +2059,7 @@ void do_meshbuts(unsigned short event)
if(button(&randfac, 1, 100, "Rand fac:")==0) return;
waitcursor(1);
fac= -( (float)randfac )/100;
- subdivideflag(1, fac, editbutflag & B_BEAUTY);
+ esubdivideflag(1, fac, editbutflag & B_BEAUTY,1,0);
countall();
waitcursor(0);
allqueue(REDRAWVIEW3D, 0);
diff --git a/source/blender/src/editmesh_add.c b/source/blender/src/editmesh_add.c
index f8518fc4a90..25249f890aa 100644
--- a/source/blender/src/editmesh_add.c
+++ b/source/blender/src/editmesh_add.c
@@ -776,7 +776,8 @@ void add_primitiveMesh(int type)
}
else if(type==12) { /* Icosphere */
EditVert *eva[12];
-
+ EditEdge *eed;
+
/* clear all flags */
eve= em->verts.first;
while(eve) {
@@ -792,14 +793,18 @@ void add_primitiveMesh(int type)
eva[a]->f= 1+2;
}
for(a=0;a<20;a++) {
- v1= eva[ icoface[a][0] ];
+ EditFace *evtemp;
+ v1= eva[ icoface[a][0] ];
v2= eva[ icoface[a][1] ];
v3= eva[ icoface[a][2] ];
- addfacelist(v1, v2, v3, 0, NULL, NULL);
+ evtemp = addfacelist(v1, v2, v3, 0, NULL, NULL);
+ evtemp->e1->f = 1+2;
+ evtemp->e2->f = 1+2;
+ evtemp->e3->f = 1+2;
}
dia*=200;
- for(a=1; a<subdiv; a++) subdivideflag(2, dia, 0);
+ for(a=1; a<subdiv; a++) esubdivideflag(2, dia, 0,1,0);
/* and now do imat */
eve= em->verts.first;
while(eve) {
@@ -809,6 +814,15 @@ void add_primitiveMesh(int type)
}
eve= eve->next;
}
+
+ // Clear the flag 2 from the edges
+ for(eed=em->edges.first;eed;eed=eed->next){
+ if(eed->f & 2){
+ eed->f &= !2;
+ }
+ }
+
+
} else if (type==13) { /* Monkey */
extern int monkeyo, monkeynv, monkeynf;
extern signed char monkeyf[][4];
diff --git a/source/blender/src/editmesh_loop.c b/source/blender/src/editmesh_loop.c
index afc63ee50f7..ca1985ba5af 100644
--- a/source/blender/src/editmesh_loop.c
+++ b/source/blender/src/editmesh_loop.c
@@ -90,67 +90,123 @@ editmesh_loop: tools with own drawing subloops, select, knife, subdiv
#include "winlay.h"
-/* *************** LOOP SELECT ************* */
-
-static short edgeFaces(EditEdge *e){
+/* New LoopCut */
+static void edgering_sel(EditEdge *startedge, int select, int previewlines){
EditMesh *em = G.editMesh;
- EditFace *search=NULL;
- short count = 0;
-
- search = em->faces.first;
- while(search){
- if((search->e1 == e || search->e2 == e) || (search->e3 == e || search->e4 == e))
- count++;
- search = search->next;
+ EditEdge *eed;
+ EditFace *efa;
+ int looking= 1,i;
+ float co[2][3];
+ EditVert *v[2][2];
+ /* in eed->f1 we put the valence (amount of faces in edge) */
+ /* in eed->f2 we put tagged flag as correct loop */
+ /* in efa->f1 we put tagged flag as correct to select */
+
+ for(eed= em->edges.first; eed; eed= eed->next) {
+ eed->f1= 0;
+ eed->f2= 0;
}
- return count;
-}
-
-/* this utility function checks to see if 2 edit edges share a face,
- returns 1 if they do
- returns 0 if they do not, or if the function is passed the same edge 2 times
-*/
-static short sharesFace(EditEdge* e1, EditEdge* e2)
-{
- EditMesh *em = G.editMesh;
- EditFace *search=NULL;
- search = em->faces.first;
- if (e1 == e2){
- return 0 ;
+ for(efa= em->faces.first; efa; efa= efa->next) {
+ efa->f1= 0;
+ if(efa->h==0) {
+ efa->e1->f1++;
+ efa->e2->f1++;
+ efa->e3->f1++;
+ if(efa->e4) efa->e4->f1++;
+ }
}
- while(search){
- if(
- ((search->e1 == e1 || search->e2 == e1) || (search->e3 == e1 || search->e4 == e1)) &&
- ((search->e1 == e2 || search->e2 == e2) || (search->e3 == e2 || search->e4 == e2))
- ) {
- return 1;
+
+ // tag startedge OK
+ startedge->f2= 1;
+
+ while(looking) {
+ looking= 0;
+
+ for(efa= em->faces.first; efa; efa= efa->next) {
+ if(efa->e4 && efa->f1==0) { // not done quad
+ if(efa->e1->f1<=2 && efa->e2->f1<=2 && efa->e3->f1<=2 && efa->e4->f1<=2) { // valence ok
+
+ // if edge tagged, select opposing edge and mark face ok
+ if(efa->e1->f2) {
+ efa->e3->f2= 1;
+ efa->f1= 1;
+ looking= 1;
+ }
+ else if(efa->e2->f2) {
+ efa->e4->f2= 1;
+ efa->f1= 1;
+ looking= 1;
+ }
+ if(efa->e3->f2) {
+ efa->e1->f2= 1;
+ efa->f1= 1;
+ looking= 1;
+ }
+ if(efa->e4->f2) {
+ efa->e2->f2= 1;
+ efa->f1= 1;
+ looking= 1;
+ }
+ }
+ }
}
- search = search->next;
}
- return 0;
+
+ if(previewlines > 0 && select == 0){
+ persp(PERSP_VIEW);
+ glPushMatrix();
+ mymultmatrix(G.obedit->obmat);
+ //glColor3ub(0, 255, 255);
+ //glBegin(GL_LINES);
+ //glVertex3f(nearest->v1->co[0],nearest->v1->co[1],nearest->v1->co[2]);
+ //glVertex3f(nearest->v2->co[0],nearest->v2->co[1],nearest->v2->co[2]);
+ //glEnd();
+ for(efa= em->faces.first; efa; efa= efa->next) {
+ if(efa->v4 == NULL) { continue; }
+ if(efa->e1->f2 == 1){
+ v[0][0] = efa->v1;
+ v[0][1] = efa->v2;
+ v[1][0] = efa->v4;
+ v[1][1] = efa->v3;
+ } else if(efa->e2->f2 == 1){
+ v[0][0] = efa->v2;
+ v[0][1] = efa->v3;
+ v[1][0] = efa->v1;
+ v[1][1] = efa->v4;
+ } else { continue; }
+
+ for(i=1;i<=previewlines;i++){
+ co[0][0] = (v[0][1]->co[0] - v[0][0]->co[0])*(i/((float)previewlines+1))+v[0][0]->co[0];
+ co[0][1] = (v[0][1]->co[1] - v[0][0]->co[1])*(i/((float)previewlines+1))+v[0][0]->co[1];
+ co[0][2] = (v[0][1]->co[2] - v[0][0]->co[2])*(i/((float)previewlines+1))+v[0][0]->co[2];
+
+ co[1][0] = (v[1][1]->co[0] - v[1][0]->co[0])*(i/((float)previewlines+1))+v[1][0]->co[0];
+ co[1][1] = (v[1][1]->co[1] - v[1][0]->co[1])*(i/((float)previewlines+1))+v[1][0]->co[1];
+ co[1][2] = (v[1][1]->co[2] - v[1][0]->co[2])*(i/((float)previewlines+1))+v[1][0]->co[2];
+ glColor3ub(255, 0, 255);
+ glBegin(GL_LINES);
+ glVertex3f(co[0][0],co[0][1],co[0][2]);
+ glVertex3f(co[1][0],co[1][1],co[1][2]);
+ glEnd();
+ }
+ }
+ glPopMatrix();
+ } else {
+
+ /* (de)select the edges */
+ for(eed= em->edges.first; eed; eed= eed->next) {
+ if(eed->f2) EM_select_edge(eed, select);
+ }
+ }
}
-/* This function selects a vertex loop based on a each succesive edge having a valance of 4
- and not sharing a face with the previous edge */
-
-/* It uses ->f flags still, which isn't causing bugs now, but better be put in ->f1 (ton) */
-
-void vertex_loop_select()
-{
- EditMesh *em = G.editMesh;
- EditVert *v1=NULL,*v2=NULL;
- EditEdge *search=NULL,*startEdge=NULL,*valSearch = NULL,*nearest = NULL,*compEdge;
- EditEdge *EdgeVal[5] = {NULL,NULL,NULL,NULL,NULL};
- short numEdges=0,curEdge = 0,looking = 1,edgeValCount = 0,i=0,looped = 0,choosing = 1,event,noloop=0,cancel=0, val;
- short protect = 0, dist= 50;
+void CutEdgeloop(int numcuts){
+ EditMesh *em = G.editMesh;
short mvalo[2] = {0,0}, mval[2];
-
- SetBlenderCursor(BC_VLOOPCURSOR);
- for(search=em->edges.first;search;search=search->next)
- numEdges++;
-
- /* start with v1 and go in one direction. */
- while(choosing){
- getmouseco_areawin(mval);
+ EditEdge* nearest,*eed;
+ short event,val,choosing=1,cancel=0,dist,cuthalf = 0;
+
+ while(choosing){
+ getmouseco_areawin(mval);
if (mval[0] != mvalo[0] || mval[1] != mvalo[1]) {
mvalo[0] = mval[0];
@@ -158,139 +214,12 @@ void vertex_loop_select()
dist= 50;
nearest = findnearestedge(&dist); // returns actual distance in dist
-
- scrarea_do_windraw(curarea); // after findnearestedge, backbuf!
-
- if (nearest && edgeFaces(nearest)==2) {
- for(search = em->edges.first;search;search=search->next)
- search->f &= ~32;
-
- compEdge = startEdge = nearest;
- nearest->f |= 32;
- curEdge = 0;
- v1 = startEdge->v1;
- v2 = startEdge->v2;
- looking = 1;
- while(looking){
- if(protect++ > numEdges) break;
- if(edgeFaces(compEdge) != 2) break;
- /*Find Edges that have v1*/
- edgeValCount = -1;
- EdgeVal[0] = EdgeVal[1] = EdgeVal[2] = NULL;
-
- for(valSearch = em->edges.first;valSearch;valSearch = valSearch->next){
- if(valSearch->v1 == v1 || valSearch->v2 == v1){
- if(valSearch != compEdge){
- if((valSearch->v1->h == 0) && (valSearch->v2->h == 0)){
- if(edgeFaces(valSearch) == 2){
- edgeValCount++;
- EdgeVal[edgeValCount] = valSearch;
- }
- }
- }
- }
- if(edgeValCount == 3)break;
- }
- /* Check that there was a valance of 4*/
- if(edgeValCount != 2){
- noloop = 1;
- looking = 0;
- break;
- }
- else{
- /* There were 3 edges, so find the one that does not share the previous edge */
- for(i=0;i<3;i++){
- if(sharesFace(compEdge,EdgeVal[i]) == 0){
- /* We went all the way around the loop */
- if(EdgeVal[i] == nearest){
- looking = 0;
- looped = 1;
- break;
- }
- else{
- /* we are still in the loop, so add the next edge*/
- curEdge++;
- EdgeVal[i]->f |= 32;
- compEdge = EdgeVal[i];
- if(compEdge->v1 == v1)
- v1 = compEdge->v2;
- else
- v1 = compEdge->v1;
- }
- }
- }
- }
- }
- compEdge = nearest;
- looking = 1;
- protect = 0;
- while(looking/* && !looped*/){
- if(protect++ > numEdges) break;
- if(edgeFaces(compEdge) != 2) break;
- /*Find Edges that have v1*/
- edgeValCount = -1;
- EdgeVal[0] = EdgeVal[1] = EdgeVal[2] = NULL;
-
- for(valSearch = em->edges.first;valSearch;valSearch = valSearch->next){
- if(valSearch->v1 == v2 || valSearch->v2 == v2){
- if(valSearch != compEdge){
- if((valSearch->v1->h == 0) && (valSearch->v2->h == 0)){
- if(edgeFaces(valSearch) == 2){
- edgeValCount++;
- EdgeVal[edgeValCount] = valSearch;
- }
- }
- }
- }
- if(edgeValCount == 3)break;
- }
- /* Check that there was a valance of 4*/
- if(edgeValCount != 2){
- noloop = 1;
- looking = 0;
- break;
- }
- else{
- /* There were 3 edges, so find the one that does not share the previous edge */
- for(i=0;i<3;i++){
- if(sharesFace(compEdge,EdgeVal[i]) == 0){
- /* We went all the way around the loop */
- if(EdgeVal[i] == nearest){
- looking = 0;
- looped = 1;
- break;
- }
- else{
- /* we are still in the loop, so add the next edge*/
- curEdge++;
- EdgeVal[i]->f |= 32;
- compEdge = EdgeVal[i];
- if(compEdge->v1 == v2)
- v2 = compEdge->v2;
- else
- v2 = compEdge->v1;
- }
- }
- }
- }
- }
- /* set up for opengl drawing in the 3d window */
- persp(PERSP_VIEW);
- glPushMatrix();
- mymultmatrix(G.obedit->obmat);
- glColor3ub(0, 255, 255);
- for(search = em->edges.first;search;search= search->next){
- if(search->f & 32){
- glBegin(GL_LINES);
- glVertex3f(search->v1->co[0],search->v1->co[1],search->v1->co[2]);
- glVertex3f(search->v2->co[0],search->v2->co[1],search->v2->co[2]);
- glEnd();
- }
- }
-
- glPopMatrix();
- }
+ scrarea_do_windraw(curarea); // after findnearestedge, backbuf!
+ /* Need to figure preview */
+ if(nearest){
+ edgering_sel(nearest, 0, numcuts);
+ }
screen_swapbuffers();
/* backbuffer refresh for non-apples (no aux) */
@@ -300,14 +229,16 @@ void vertex_loop_select()
}
#endif
}
- else PIL_sleep_ms(10); // idle
-
+ else PIL_sleep_ms(10); // idle
while(qtest())
{
val=0;
event= extern_qread(&val);
if(val && ((event==LEFTMOUSE || event==RETKEY) || event == MIDDLEMOUSE))
{
+ if(event == MIDDLEMOUSE){
+ cuthalf = 1;
+ }
if (nearest==NULL)
cancel = 1;
choosing=0;
@@ -319,65 +250,90 @@ void vertex_loop_select()
cancel = 1;
break;
}
- if(val && (event==BKEY && G.qual==LR_ALTKEY ))
- {
-
- SetBlenderCursor(SYSCURSOR);
- loopoperations(LOOP_SELECT);
- return;
- }
- }
- }
- if(!cancel){
- /* If this is a unmodified select, clear the selection */
-
- /* XXX note that !1 is 0, so it not only clears bit 1 (ton) */
- if(!(G.qual & LR_SHIFTKEY) && !(G.qual & LR_ALTKEY)){
- for(search = em->edges.first;search;search= search->next){
- search->v1->f &= !1;
- search->v2->f &= !1;
- }
- EM_clear_flag_all(SELECT); /* XXX probably that's sufficient */
- }
- /* Alt was not pressed, so add to the selection */
- if(!(G.qual & LR_ALTKEY)){
- for(search = em->edges.first;search;search= search->next){
- if(search->f & 32){
- search->v1->f |= 1;
- search->v2->f |= 1;
- }
- search->f &= ~32;
+ if(val && (event==PADPLUSKEY || event==WHEELUPMOUSE))
+ {
+ numcuts++;
+ mvalo[0] = 0;mvalo[1] = 0;
+ break;
}
- /* XXX this will correctly flush */
- }
- /* alt was pressed, so subtract from the selection */
- else
- {
- /* XXX this doesnt flush correct in face select mode */
- for(search = em->edges.first;search;search= search->next){
- if(search->f & 32){
- search->v1->f &= !1;
- search->v2->f &= !1;
- EM_select_edge(search, 0); // the call to deselect edge
- }
- search->f &= ~32;
+ if(val && (event==PADMINUS || event==WHEELDOWNMOUSE))
+ {
+ if(numcuts > 1){
+ numcuts--;
+ mvalo[0] = 0;mvalo[1] = 0;
+ break;
+ }
}
- }
-
- EM_select_flush(); // flushes vertex -> edge -> face selection
-
- countall();
-
- BIF_undo_push("Select Vertex Loop");
- }
-
- addqueue(curarea->win, REDRAW, 1);
- SetBlenderCursor(SYSCURSOR);
- return;
+ }
+ }
+ if(cancel){
+ return;
+ }
+ /* clean selection */
+ for(eed=em->edges.first; eed; eed = eed->next){
+ EM_select_edge(eed,0);
+ }
+ /* select edge ring */
+ edgering_sel(nearest, 1, 0);
+
+ /* now cut the loops */
+ esubdivideflag(SELECT,0,0,numcuts,1);
+
+ force_draw(0);
+ makeDispList(G.obedit);
+ scrarea_queue_winredraw(curarea);
+
+ /* if this was a single cut, enter edgeslide mode */
+ if(numcuts == 1){
+ if(cuthalf)
+ EdgeSlide(1,0.0);
+ else
+ EdgeSlide(0,0.0);
+ }
+
+ return;
}
-/* *********** END LOOP SELECT ********** */
+/* *************** LOOP SELECT ************* */
+
+static short edgeFaces(EditEdge *e){
+ EditMesh *em = G.editMesh;
+ EditFace *search=NULL;
+ short count = 0;
+
+ search = em->faces.first;
+ while(search){
+ if((search->e1 == e || search->e2 == e) || (search->e3 == e || search->e4 == e))
+ count++;
+ search = search->next;
+ }
+ return count;
+}
+
+/* this utility function checks to see if 2 edit edges share a face,
+ returns 1 if they do
+ returns 0 if they do not, or if the function is passed the same edge 2 times
+*/
+short sharesFace(EditEdge* e1, EditEdge* e2)
+{
+ EditMesh *em = G.editMesh;
+ EditFace *search=NULL;
+ search = em->faces.first;
+ if (e1 == e2){
+ return 0 ;
+ }
+ while(search){
+ if(
+ ((search->e1 == e1 || search->e2 == e1) || (search->e3 == e1 || search->e4 == e1)) &&
+ ((search->e1 == e2 || search->e2 == e2) || (search->e3 == e2 || search->e4 == e2))
+ ) {
+ return 1;
+ }
+ search = search->next;
+ }
+ return 0;
+}
/* ***************** TRAIL ************************
@@ -549,6 +505,7 @@ void KnifeSubdivide(char mode)
CutCurve *curve;
EditEdge *eed;
Window *win;
+ short numcuts=1;
if (G.obedit==0) return;
@@ -558,11 +515,15 @@ void KnifeSubdivide(char mode)
}
if (mode==KNIFE_PROMPT) {
- short val= pupmenu("Cut Type %t|Exact Line%x1|Midpoints%x2");
+ short val= pupmenu("Cut Type %t|Exact Line%x1|Midpoints%x2|Multicut%x3");
if(val<1) return;
- mode= val; // warning, mode is char, pupmenu returns -1 with ESC
+ mode = val; // warning, mode is char, pupmenu returns -1 with ESC
}
+ if(mode == KNIFE_MULTICUT) {
+ if(button(&numcuts, 2, 128, "Number of Cuts:")==0) return;
+ }
+
calc_meshverts_ext(); /*Update screen coords for current window */
/* Set a knife cursor here */
@@ -591,9 +552,10 @@ void KnifeSubdivide(char mode)
eed= eed->next;
}
- if (mode==1) subdivideflag(1, 0, B_KNIFE|B_PERCENTSUBD);
- else if (mode==2) subdivideflag(1, 0, B_KNIFE);
-
+ if (mode==KNIFE_EXACT) esubdivideflag(1, 0, B_KNIFE|B_PERCENTSUBD,1,0);
+ else if (mode==KNIFE_MIDPOINT) esubdivideflag(1, 0, B_KNIFE,1,0);
+ else if (mode==KNIFE_MULTICUT) esubdivideflag(1, 0, B_KNIFE,numcuts,0);
+
eed=em->edges.first;
while(eed){
eed->f2=0;
@@ -718,1103 +680,26 @@ short seg_intersect(EditEdge *e, CutCurve *c, int len){
return(isect);
}
-/* ******************** LOOP ******************************************* */
-
-/* XXX: this loop function is totally out of control!
- can be half the code, and using structured functions (ton) */
-
-/*
-functionality: various loop functions
-parameters: mode tells the function what it should do with the loop:
- LOOP_SELECT = select
- LOOP_CUT = cut in half
-*/
-
-void loopoperations(char mode)
-{
- EditMesh *em = G.editMesh;
- EditVert* look = NULL;
- EditEdge *start, *eed, *opposite,*currente, *oldstart;
- EditEdge **tagged = NULL,**taggedsrch = NULL,*close;
- EditFace *efa,**percentfacesloop = NULL, *currentvl, *formervl;
- short lastface=0, foundedge=0, c=0, tri=0, side=1, totface=0, searching=1, event=0, noface=1;
- short skip,nextpos,percentfaces, dist=50;
-
- int i=0,ect=0,j=0,k=0,cut,smooth,timesthrough=0,inset = 0;
-
- float percentcut, outcut;
-
- char mesg[100];
-
- if ((G.obedit==0) || (em->faces.first==0)) return;
-
- SetBlenderCursor(BC_VLOOPCURSOR);
-
- /* Clear flags */
- for(eed=em->edges.first; eed; eed=eed->next) eed->f2= 0;
- for(efa= em->faces.first; efa; efa=efa->next) efa->f1= 0;
-
- start=NULL;
- oldstart=NULL;
-
- while(searching){
-
- /* reset variables */
- start=eed=opposite=currente=0;
- efa=currentvl=formervl=0;
- side=noface=1;
- lastface=foundedge=c=tri=totface=0;
-
- //start=findnearestvisibleedge();
- dist= 50;
- start= findnearestedge(&dist);
-
- /* used flags in the code:
- vertex->f & 2: in findnearestvisibleedge
- edge->f2 : subdiv codes
- efa->f1 : subdiv codes
- */
-
- /* If the edge doesn't belong to a face, it's not a valid starting edge */
- /* and only accept starting edge if it is part of at least one visible face */
- if(start){
- start->f2 |= 16;
- efa=em->faces.first;
- while(efa){
- /* since this edge is on the face, check if the face is hidden */
- if( efa->h==0 ){
- if(efa->e1->f2 & 16){
- noface=0;
- efa->e1->f2 &= ~16;
- }
- else if(efa->e2->f2 & 16){
- noface=0;
- efa->e2->f2 &= ~16;
- }
- else if(efa->e3->f2 & 16){
- noface=0;
- efa->e3->f2 &= ~16;
- }
- else if(efa->e4 && (efa->e4->f2 & 16)){
- noface=0;
- efa->e4->f2 &= ~16;
- }
- }
- efa=efa->next;
- }
- }
-
- /* Did we find anything that is selectable? */
- if(start && !noface && (oldstart==NULL || start!=oldstart)){
-
- /* If we stay in the neighbourhood of this edge, we don't have to recalculate the loop everytime*/
- oldstart=start;
-
- /* Clear flags */
- for(eed=em->edges.first; eed; eed=eed->next){
- eed->f2 &= ~(2|4|8|32|64);
- eed->v1->f &= ~(2|8|16); // xxxx
- eed->v2->f &= ~(2|8|16);
- }
-
- for(efa= em->faces.first; efa; efa=efa->next){
- efa->f1 &= ~(4|8);
- totface++;
- }
-
- /* Tag the starting edge */
- start->f2 |= (2|4|8|64);
- start->v1->f |= 2; /* xxxx */
- start->v2->f |= 2;
-
- currente=start;
-
- /*-----Limit the Search----- */
- while(!lastface && c<totface+1){
-
- /*----------Get Loop------------------------*/
- tri=foundedge=lastface=0;
- efa= em->faces.first;
- while(efa && !foundedge && !tri){
-
- if(!(efa->v4)){ /* Exception for triangular faces */
-
- if((efa->e1->f2 | efa->e2->f2 | efa->e3->f2) & 2){
- if(!(efa->f1 & 4)){
- tri=1;
- currentvl=efa;
- if(side==1) efa->f1 |= 4;
- }
- }
- }
- else{
-
- if((efa->e1->f2 | efa->e2->f2 | efa->e3->f2 | efa->e4->f2) & 2){
-
- if(c==0){ /* just pick a face, doesn't matter wich side of the edge we go to */
- if(!(efa->f1 & 4)){
-
- if(!(efa->e1->v1->f & 2) && !(efa->e1->v2->f & 2)){ // xxxxx
- if(efa->e1->h==0){
- opposite=efa->e1;
- foundedge=1;
- }
- }
- else if(!(efa->e2->v1->f & 2) && !(efa->e2->v2->f & 2)){ // xxxx
- if(efa->e2->h==0){
- opposite=efa->e2;
- foundedge=1;
- }
- }
- else if(!(efa->e3->v1->f & 2) && !(efa->e3->v2->f & 2)){
- if(efa->e3->h==0){
- opposite=efa->e3;
- foundedge=1;
- }
- }
- else if(!(efa->e4->v1->f & 2) && !(efa->e4->v2->f & 2)){
- if(efa->e4->h==0){
- opposite=efa->e4;
- foundedge=1;
- }
- }
-
- if(foundedge){
- currentvl=efa;
- formervl=efa;
-
- /* mark this side of the edge so we know in which direction we went */
- if(side==1) efa->f1 |= 4;
- }
- }
- }
- else {
- if(efa!=formervl){ /* prevent going backwards in the loop */
-
- if(!(efa->e1->v1->f & 2) && !(efa->e1->v2->f & 2)){
- if(efa->e1->h==0){
- opposite=efa->e1;
- foundedge=1;
- }
- }
- else if(!(efa->e2->v1->f & 2) && !(efa->e2->v2->f & 2)){
- if(efa->e2->h==0){
- opposite=efa->e2;
- foundedge=1;
- }
- }
- else if(!(efa->e3->v1->f & 2) && !(efa->e3->v2->f & 2)){
- if(efa->e3->h==0){
- opposite=efa->e3;
- foundedge=1;
- }
- }
- else if(!(efa->e4->v1->f & 2) && !(efa->e4->v2->f & 2)){
- if(efa->e4->h==0){
- opposite=efa->e4;
- foundedge=1;
- }
- }
-
- currentvl=efa;
- }
- }
- }
- }
- efa=efa->next;
- }
- /*----------END Get Loop------------------------*/
-
-
- /*----------Decisions-----------------------------*/
- if(foundedge){
- /* mark the edge and face as done */
- currente->f2 |= 8;
- currentvl->f1 |= 8;
-
- if(opposite->f2 & 4) lastface=1; /* found the starting edge! close loop */
- else{
- /* un-set the testflags */
- currente->f2 &= ~2;
- currente->v1->f &= ~2; // xxxx
- currente->v2->f &= ~2;
-
- /* set the opposite edge to be the current edge */
- currente=opposite;
-
- /* set the current face to be the FORMER face (to prevent going backwards in the loop) */
- formervl=currentvl;
-
- /* set the testflags */
- currente->f2 |= 2;
- currente->v1->f |= 2; // xxxx
- currente->v2->f |= 2;
- }
- c++;
- }
- else{
- /* un-set the testflags */
- currente->f2 &= ~2;
- currente->v1->f &= ~2; // xxxx
- currente->v2->f &= ~2;
-
- /* mark the edge and face as done */
- currente->f2 |= 8;
- currentvl->f1 |= 8;
-
-
-
- /* is the the first time we've ran out of possible faces?
- * try to start from the beginning but in the opposite direction go as far as possible
- */
- if(side==1){
- if(tri)tri=0;
- currente=start;
- currente->f2 |= 2;
- currente->v1->f |= 2; // xxxx
- currente->v2->f |= 2;
- side++;
- c=0;
- }
- else lastface=1;
- }
- /*----------END Decisions-----------------------------*/
-
- }
- /*-----END Limit the Search----- */
-
-
- /*------------- Preview lines--------------- */
-
- /* uses callback mechanism to draw it all in current area */
- scrarea_do_windraw(curarea);
-
- /* set window matrix to perspective, default an area returns with buttons transform */
- persp(PERSP_VIEW);
- /* make a copy, for safety */
- glPushMatrix();
- /* multiply with the object transformation */
- mymultmatrix(G.obedit->obmat);
-
- glColor3ub(255, 255, 0);
-
- if(mode==LOOP_SELECT){
- efa= em->faces.first;
- while(efa){
- if(efa->f1 & 8){
-
- if(!(efa->e1->f2 & 8)){
- glBegin(GL_LINES);
- glVertex3fv(efa->e1->v1->co);
- glVertex3fv(efa->e1->v2->co);
- glEnd();
- }
-
- if(!(efa->e2->f2 & 8)){
- glBegin(GL_LINES);
- glVertex3fv(efa->e2->v1->co);
- glVertex3fv(efa->e2->v2->co);
- glEnd();
- }
-
- if(!(efa->e3->f2 & 8)){
- glBegin(GL_LINES);
- glVertex3fv(efa->e3->v1->co);
- glVertex3fv(efa->e3->v2->co);
- glEnd();
- }
-
- if(efa->e4){
- if(!(efa->e4->f2 & 8)){
- glBegin(GL_LINES);
- glVertex3fv(efa->e4->v1->co);
- glVertex3fv(efa->e4->v2->co);
- glEnd();
- }
- }
- }
- efa=efa->next;
- }
- }
-
- if(mode==LOOP_CUT){
- efa= em->faces.first;
- while(efa){
- if(efa->f1 & 8){
- float cen[2][3];
- int a=0;
-
- efa->v1->f &= ~8; // xxx
- efa->v2->f &= ~8;
- efa->v3->f &= ~8;
- if(efa->v4)efa->v4->f &= ~8;
-
- if(efa->e1->f2 & 8){
- cen[a][0]= (efa->e1->v1->co[0] + efa->e1->v2->co[0])/2.0;
- cen[a][1]= (efa->e1->v1->co[1] + efa->e1->v2->co[1])/2.0;
- cen[a][2]= (efa->e1->v1->co[2] + efa->e1->v2->co[2])/2.0;
-
- efa->e1->v1->f |= 8; // xxx
- efa->e1->v2->f |= 8;
-
- a++;
- }
- if((efa->e2->f2 & 8) && a!=2){
- cen[a][0]= (efa->e2->v1->co[0] + efa->e2->v2->co[0])/2.0;
- cen[a][1]= (efa->e2->v1->co[1] + efa->e2->v2->co[1])/2.0;
- cen[a][2]= (efa->e2->v1->co[2] + efa->e2->v2->co[2])/2.0;
-
- efa->e2->v1->f |= 8; // xxx
- efa->e2->v2->f |= 8;
-
- a++;
- }
- if((efa->e3->f2 & 8) && a!=2){
- cen[a][0]= (efa->e3->v1->co[0] + efa->e3->v2->co[0])/2.0;
- cen[a][1]= (efa->e3->v1->co[1] + efa->e3->v2->co[1])/2.0;
- cen[a][2]= (efa->e3->v1->co[2] + efa->e3->v2->co[2])/2.0;
-
- efa->e3->v1->f |= 8; // xxx
- efa->e3->v2->f |= 8;
-
- a++;
- }
-
- if(efa->e4){
- if((efa->e4->f2 & 8) && a!=2){
- cen[a][0]= (efa->e4->v1->co[0] + efa->e4->v2->co[0])/2.0;
- cen[a][1]= (efa->e4->v1->co[1] + efa->e4->v2->co[1])/2.0;
- cen[a][2]= (efa->e4->v1->co[2] + efa->e4->v2->co[2])/2.0;
-
- efa->e4->v1->f |= 8; // xxx
- efa->e4->v2->f |= 8;
-
- a++;
- }
- }
- else{ /* if it's a triangular face, set the remaining vertex as the cutcurve coordinate */
- if(!(efa->v1->f & 8) && efa->v1->h==0){ // xxx
- cen[a][0]= efa->v1->co[0];
- cen[a][1]= efa->v1->co[1];
- cen[a][2]= efa->v1->co[2];
- a++;
- }
- else if(!(efa->v2->f & 8) && efa->v2->h==0){
- cen[a][0]= efa->v2->co[0];
- cen[a][1]= efa->v2->co[1];
- cen[a][2]= efa->v2->co[2];
- a++;
- }
- else if(!(efa->v3->f & 8) && efa->v3->h==0){
- cen[a][0]= efa->v3->co[0];
- cen[a][1]= efa->v3->co[1];
- cen[a][2]= efa->v3->co[2];
- a++;
- }
- }
-
- if(a==2){
- glBegin(GL_LINES);
-
- glVertex3fv(cen[0]);
- glVertex3fv(cen[1]);
-
- glEnd();
- }
- }
- efa=efa->next;
- }
-
- eed=em->edges.first;
- while(eed){
- if(eed->f2 & 64){
- glBegin(GL_LINES);
- glColor3ub(200, 255, 200);
- glVertex3fv(eed->v1->co);
- glVertex3fv(eed->v2->co);
- glEnd();
- eed=0;
- }else{
- eed = eed->next;
- }
- }
- }
-
- /* restore matrix transform */
- glPopMatrix();
-
- headerprint("LMB to confirm, RMB to cancel");
-
- /* this also verifies other area/windows for clean swap */
- screen_swapbuffers();
-
- /* backbuffer refresh for non-apples (no aux) */
-#ifndef __APPLE__
- if(G.vd->drawtype>OB_WIRE && (G.vd->flag & V3D_ZBUF_SELECT)) {
- backdrawview3d(0);
- }
-#endif
-
- /*--------- END Preview Lines------------*/
-
- }/*if(start!=NULL){ */
- else PIL_sleep_ms(10); // idle
-
- while(qtest()) {
- unsigned short val=0;
- event= extern_qread(&val); /* extern_qread stores important events for the mainloop to handle */
-
- /* val==0 on key-release event */
- if(val && (event==ESCKEY || event==RIGHTMOUSE || event==LEFTMOUSE || event==RETKEY || event == MIDDLEMOUSE)){
- searching=0;
- }
- }
-
- }/*while(event!=ESCKEY && event!=RIGHTMOUSE && event!=LEFTMOUSE && event!=RETKEY){*/
-
- /*----------Select Loop------------*/
- if(mode==LOOP_SELECT && start!=NULL && ((event==LEFTMOUSE || event==RETKEY) || event == MIDDLEMOUSE || event == BKEY)){
-
- /* If this is a unmodified select, clear the selection */
- if(!(G.qual & LR_SHIFTKEY) && !(G.qual & LR_ALTKEY)){
- for(efa= em->faces.first;efa;efa=efa->next){
- EM_select_face(efa, 0); // and this is correct deselect face
- }
- }
- /* Alt was not pressed, so add to the selection */
- if(!(G.qual & LR_ALTKEY)){
- for(efa= em->faces.first;efa;efa=efa->next){
- if(efa->f1 & 8){
- EM_select_face(efa, 1); // and this is correct select face
- }
- }
- }
- /* alt was pressed, so subtract from the selection */
- else
- {
- for(efa= em->faces.first;efa;efa=efa->next){
- if(efa->f1 & 8){
- EM_select_face(efa, 0); // this is correct deselect face
- }
- }
- }
-
- }
- /*----------END Select Loop------------*/
-
- /*----------Cut Loop---------------*/
- if(mode==LOOP_CUT && start!=NULL && (event==LEFTMOUSE || event==RETKEY)){
-
- /* count the number of edges in the loop */
- for(eed=em->edges.first; eed; eed = eed->next){
- if(eed->f2 & 8)
- ect++;
- }
-
- tagged = MEM_mallocN(ect*sizeof(EditEdge*), "tagged");
- taggedsrch = MEM_mallocN(ect*sizeof(EditEdge*), "taggedsrch");
- for(i=0;i<ect;i++)
- {
- tagged[i] = NULL;
- taggedsrch[i] = NULL;
- }
- ect = 0;
- for(eed=em->edges.first; eed; eed = eed->next){
- if(eed->f2 & 8)
- {
- if(eed->h==0){
- eed->v1->f |= SELECT;
- eed->v2->f |= SELECT;
- eed->f |= SELECT;
- tagged[ect] = eed;
- eed->f2 &= ~(32);
- ect++;
- }
- }
- }
- taggedsrch[0] = tagged[0];
-
- while(timesthrough < 2)
- {
- i=0;
- while(i < ect){/*Look at the members of the search array to line up cuts*/
- if(taggedsrch[i]==NULL)break;
- for(j=0;j<ect;j++){ /*Look through the list of tagged verts for connected edges*/
- int addededge = 0;
- if(taggedsrch[i]->f2 & 32) /*If this edgee is marked as flipped, use vert 2*/
- look = taggedsrch[i]->v2;
- else /*else use vert 1*/
- look = taggedsrch[i]->v1;
-
- if(taggedsrch[i] == tagged[j])
- continue; /*If we are looking at the same edge, skip it*/
-
- skip = 0;
- for(k=0;k<ect;k++) {
- if(taggedsrch[k] == NULL) /*go to empty part of search list without finding*/
- break;
- if(tagged[j] == taggedsrch[k]){ /*We found a match already in the list*/
- skip = 1;
- break;
- }
- }
- if(skip)
- continue;
- nextpos = 0;
- if(findedgelist(look,tagged[j]->v2)){
- while(nextpos < ect){ /*Find the first open spot in the search array*/
- if(taggedsrch[nextpos] == NULL){
- taggedsrch[nextpos] = tagged[j]; /*put tagged[j] in it*/
- taggedsrch[nextpos]->f2 |= 32;
- addededge = 1;
- break;
- }
- else
- nextpos++;
- }
- } /* End else if connected to vert 2*/
- else if(findedgelist(look,tagged[j]->v1)){ /*If our vert is connected to vert 1 */
- while(nextpos < ect){ /*Find the first open spot in the search array */
- if(taggedsrch[nextpos] == NULL){
- taggedsrch[nextpos] = tagged[j]; /*put tagged[j] in it*/
- addededge = 1;
- break;
- }
- else
- nextpos++;
- }
- }
-
- if(addededge)
- {
- break;
- }
- }/* End Outer For (j)*/
- i++;
- } /* End while(j<ect)*/
- timesthrough++;
- } /*end while timesthrough */
- percentcut = 0.50;
- searching = 1;
- cut = 1;
- smooth = 0;
- close = NULL;
-
-
- /* Count the Number of Faces in the selected loop*/
- percentfaces = 0;
- for(efa= em->faces.first; efa ;efa=efa->next){
- if(efa->f1 & 8)
- {
- percentfaces++;
- }
- }
-
- /* create a dynamic array for those face pointers */
- percentfacesloop = MEM_mallocN(percentfaces*sizeof(EditFace*), "percentage");
-
- /* put those faces in the array */
- i=0;
- for(efa= em->faces.first; efa ;efa=efa->next){
- if(efa->f1 & 8)
- {
- percentfacesloop[i] = efa;
- i++;
- }
- }
-
- while(searching){
-
- /* For the % calculation */
- short mval[2];
- float labda, rc[2], len, slen=0.0;
- float v1[2], v2[2], v3[2];
-
- /*------------- Percent Cut Preview Lines--------------- */
- scrarea_do_windraw(curarea);
- persp(PERSP_VIEW);
- glPushMatrix();
- mymultmatrix(G.obedit->obmat);
- glColor3ub(0, 255, 255);
-
- /*Put the preview lines where they should be for the percentage selected.*/
-
- for(i=0;i<percentfaces;i++){
- efa = percentfacesloop[i];
- for(eed = em->edges.first; eed; eed=eed->next){
- if(eed->f2 & 64){ /* color the starting edge */
- glBegin(GL_LINES);
-
- glColor3ub(200, 255, 200);
- glVertex3fv(eed->v1->co);
- glVertex3fv(eed->v2->co);
-
- glEnd();
-
- glPointSize(5);
- glBegin(GL_POINTS);
- glColor3ub(255,0,255);
-
- if(eed->f2 & 32)
- glVertex3fv(eed->v2->co);
- else
- glVertex3fv(eed->v1->co);
- glEnd();
-
-
- /*Get Starting Edge Length*/
- slen = sqrt((eed->v1->co[0]-eed->v2->co[0])*(eed->v1->co[0]-eed->v2->co[0])+
- (eed->v1->co[1]-eed->v2->co[1])*(eed->v1->co[1]-eed->v2->co[1])+
- (eed->v1->co[2]-eed->v2->co[2])*(eed->v1->co[2]-eed->v2->co[2]));
- }
- }
-
- if(!inset){
- glColor3ub(0,255,255);
- if(efa->f1 & 8)
- {
- float cen[2][3];
- int a=0;
-
- efa->v1->f &= ~8; // xxx
- efa->v2->f &= ~8;
- efa->v3->f &= ~8;
- if(efa->v4)efa->v4->f &= ~8;
-
- if(efa->e1->f2 & 8){
- float pct;
- if(efa->e1->f2 & 32)
- pct = 1-percentcut;
- else
- pct = percentcut;
- cen[a][0]= efa->e1->v1->co[0] - ((efa->e1->v1->co[0] - efa->e1->v2->co[0]) * (pct));
- cen[a][1]= efa->e1->v1->co[1] - ((efa->e1->v1->co[1] - efa->e1->v2->co[1]) * (pct));
- cen[a][2]= efa->e1->v1->co[2] - ((efa->e1->v1->co[2] - efa->e1->v2->co[2]) * (pct));
- efa->e1->v1->f |= 8; // xxx
- efa->e1->v2->f |= 8;
- a++;
- }
- if((efa->e2->f2 & 8) && a!=2)
- {
- float pct;
- if(efa->e2->f2 & 32)
- pct = 1-percentcut;
- else
- pct = percentcut;
- cen[a][0]= efa->e2->v1->co[0] - ((efa->e2->v1->co[0] - efa->e2->v2->co[0]) * (pct));
- cen[a][1]= efa->e2->v1->co[1] - ((efa->e2->v1->co[1] - efa->e2->v2->co[1]) * (pct));
- cen[a][2]= efa->e2->v1->co[2] - ((efa->e2->v1->co[2] - efa->e2->v2->co[2]) * (pct));
-
- efa->e2->v1->f |= 8; // xxx
- efa->e2->v2->f |= 8;
-
- a++;
- }
- if((efa->e3->f2 & 8) && a!=2){
- float pct;
- if(efa->e3->f2 & 32)
- pct = 1-percentcut;
- else
- pct = percentcut;
- cen[a][0]= efa->e3->v1->co[0] - ((efa->e3->v1->co[0] - efa->e3->v2->co[0]) * (pct));
- cen[a][1]= efa->e3->v1->co[1] - ((efa->e3->v1->co[1] - efa->e3->v2->co[1]) * (pct));
- cen[a][2]= efa->e3->v1->co[2] - ((efa->e3->v1->co[2] - efa->e3->v2->co[2]) * (pct));
-
- efa->e3->v1->f |= 8; // xxx
- efa->e3->v2->f |= 8;
-
- a++;
- }
-
- if(efa->e4){
- if((efa->e4->f2 & 8) && a!=2){
- float pct;
- if(efa->e4->f2 & 32)
- pct = 1-percentcut;
- else
- pct = percentcut;
- cen[a][0]= efa->e4->v1->co[0] - ((efa->e4->v1->co[0] - efa->e4->v2->co[0]) * (pct));
- cen[a][1]= efa->e4->v1->co[1] - ((efa->e4->v1->co[1] - efa->e4->v2->co[1]) * (pct));
- cen[a][2]= efa->e4->v1->co[2] - ((efa->e4->v1->co[2] - efa->e4->v2->co[2]) * (pct));
-
- efa->e4->v1->f |= 8; // xxx
- efa->e4->v2->f |= 8;
-
- a++;
- }
- }
- else { /* if it's a triangular face, set the remaining vertex as the cutcurve coordinate */
- if(!(efa->v1->f & 8) && efa->v1->h==0){ // xxx
- cen[a][0]= efa->v1->co[0];
- cen[a][1]= efa->v1->co[1];
- cen[a][2]= efa->v1->co[2];
- a++;
- }
- else if(!(efa->v2->f & 8) && efa->v2->h==0){ // xxx
- cen[a][0]= efa->v2->co[0];
- cen[a][1]= efa->v2->co[1];
- cen[a][2]= efa->v2->co[2];
- a++;
- }
- else if(!(efa->v3->f & 8) && efa->v3->h==0){ // xxx
- cen[a][0]= efa->v3->co[0];
- cen[a][1]= efa->v3->co[1];
- cen[a][2]= efa->v3->co[2];
- a++;
- }
- }
-
- if(a==2){
- glBegin(GL_LINES);
-
- glVertex3fv(cen[0]);
- glVertex3fv(cen[1]);
-
- glEnd();
- }
- }
- }/* end preview line drawing */
- else{
- glColor3ub(0,128,255);
- if(efa->f1 & 8)
- {
- float cen[2][3];
- int a=0;
-
- efa->v1->f &= ~8; // xxx
- efa->v2->f &= ~8;
- efa->v3->f &= ~8;
- if(efa->v4)efa->v4->f &= ~8;
-
- if(efa->e1->f2 & 8){
- float nlen,npct;
-
- nlen = sqrt((efa->e1->v1->co[0] - efa->e1->v2->co[0])*(efa->e1->v1->co[0] - efa->e1->v2->co[0])+
- (efa->e1->v1->co[1] - efa->e1->v2->co[1])*(efa->e1->v1->co[1] - efa->e1->v2->co[1])+
- (efa->e1->v1->co[2] - efa->e1->v2->co[2])*(efa->e1->v1->co[2] - efa->e1->v2->co[2]));
- npct = (percentcut*slen)/nlen;
- if(npct >= 1) npct = 1;
- if(efa->e1->f2 & 32) npct = 1-npct;
-
- cen[a][0]= efa->e1->v1->co[0] - ((efa->e1->v1->co[0] - efa->e1->v2->co[0]) * (npct));
- cen[a][1]= efa->e1->v1->co[1] - ((efa->e1->v1->co[1] - efa->e1->v2->co[1]) * (npct));
- cen[a][2]= efa->e1->v1->co[2] - ((efa->e1->v1->co[2] - efa->e1->v2->co[2]) * (npct));
-
- efa->e1->f1 = 32768*(npct);
- efa->e1->v1->f |= 8; // xxx
- efa->e1->v2->f |= 8;
- a++;
- }
- if((efa->e2->f2 & 8) && a!=2)
- {
- float nlen,npct;
-
- nlen = sqrt((efa->e2->v1->co[0] - efa->e2->v2->co[0])*(efa->e2->v1->co[0] - efa->e2->v2->co[0])+
- (efa->e2->v1->co[1] - efa->e2->v2->co[1])*(efa->e2->v1->co[1] - efa->e2->v2->co[1])+
- (efa->e2->v1->co[2] - efa->e2->v2->co[2])*(efa->e2->v1->co[2] - efa->e2->v2->co[2]));
- npct = (percentcut*slen)/nlen;
- if(npct >= 1) npct = 1;
- if(efa->e2->f2 & 32) npct = 1-npct;
-
- cen[a][0]= efa->e2->v1->co[0] - ((efa->e2->v1->co[0] - efa->e2->v2->co[0]) * (npct));
- cen[a][1]= efa->e2->v1->co[1] - ((efa->e2->v1->co[1] - efa->e2->v2->co[1]) * (npct));
- cen[a][2]= efa->e2->v1->co[2] - ((efa->e2->v1->co[2] - efa->e2->v2->co[2]) * (npct));
-
- efa->e2->f1 = 32768*(npct);
- efa->e2->v1->f |= 8; // xxx
- efa->e2->v2->f |= 8;
- a++;
- }
- if((efa->e3->f2 & 8) && a!=2){
- float nlen,npct;
-
- nlen = sqrt((efa->e3->v1->co[0] - efa->e3->v2->co[0])*(efa->e3->v1->co[0] - efa->e3->v2->co[0])+
- (efa->e3->v1->co[1] - efa->e3->v2->co[1])*(efa->e3->v1->co[1] - efa->e3->v2->co[1])+
- (efa->e3->v1->co[2] - efa->e3->v2->co[2])*(efa->e3->v1->co[2] - efa->e3->v2->co[2]));
- npct = (percentcut*slen)/nlen;
- if(npct >= 1) npct = 1;
- if(efa->e3->f2 & 32) npct = 1-npct;
-
- cen[a][0]= efa->e3->v1->co[0] - ((efa->e3->v1->co[0] - efa->e3->v2->co[0]) * (npct));
- cen[a][1]= efa->e3->v1->co[1] - ((efa->e3->v1->co[1] - efa->e3->v2->co[1]) * (npct));
- cen[a][2]= efa->e3->v1->co[2] - ((efa->e3->v1->co[2] - efa->e3->v2->co[2]) * (npct));
-
- efa->e3->f1 = 32768*(npct);
- efa->e3->v1->f |= 8; // xxx
- efa->e3->v2->f |= 8;
- a++;
- }
-
- if(efa->e4){
- if((efa->e4->f2 & 8) && a!=2){
- float nlen,npct;
-
- nlen = sqrt((efa->e4->v1->co[0] - efa->e4->v2->co[0])*(efa->e4->v1->co[0] - efa->e4->v2->co[0])+
- (efa->e4->v1->co[1] - efa->e4->v2->co[1])*(efa->e4->v1->co[1] - efa->e4->v2->co[1])+
- (efa->e4->v1->co[2] - efa->e4->v2->co[2])*(efa->e4->v1->co[2] - efa->e4->v2->co[2]));
- npct = (percentcut*slen)/nlen;
- if(npct >= 1) npct = 1;
- if(efa->e4->f2 & 32) npct = 1-npct;
-
- cen[a][0]= efa->e4->v1->co[0] - ((efa->e4->v1->co[0] - efa->e4->v2->co[0]) * (npct));
- cen[a][1]= efa->e4->v1->co[1] - ((efa->e4->v1->co[1] - efa->e4->v2->co[1]) * (npct));
- cen[a][2]= efa->e4->v1->co[2] - ((efa->e4->v1->co[2] - efa->e4->v2->co[2]) * (npct));
-
- efa->e4->f1 = 32768*(npct);
- efa->e4->v1->f |= 8; // xxx
- efa->e4->v2->f |= 8;
- a++;
- }
- }
- else { /* if it's a triangular face, set the remaining vertex as the cutcurve coordinate */
- if(!(efa->v1->f & 8) && efa->v1->h==0){ // xxx
- cen[a][0]= efa->v1->co[0];
- cen[a][1]= efa->v1->co[1];
- cen[a][2]= efa->v1->co[2];
- a++;
- }
- else if(!(efa->v2->f & 8) && efa->v2->h==0){ // xxx
- cen[a][0]= efa->v2->co[0];
- cen[a][1]= efa->v2->co[1];
- cen[a][2]= efa->v2->co[2];
- a++;
- }
- else if(!(efa->v3->f & 8) && efa->v3->h==0){ // xxx
- cen[a][0]= efa->v3->co[0];
- cen[a][1]= efa->v3->co[1];
- cen[a][2]= efa->v3->co[2];
- a++;
- }
- }
-
- if(a==2){
- glBegin(GL_LINES);
-
- glVertex3fv(cen[0]);
- glVertex3fv(cen[1]);
-
- glEnd();
- }
- }
- }
- }
- /* restore matrix transform */
-
- glPopMatrix();
-
- /*--------- END Preview Lines------------*/
- while(qtest())
- {
- unsigned short val=0;
- event= extern_qread(&val); /* extern_qread stores important events for the mainloop to handle */
- /* val==0 on key-release event */
-
- if(val && (event==SKEY))
- {
- if(smooth)smooth = 0;
- else smooth = 1;
- }
-
- if(val && (event==PKEY))
- {
- if(inset)inset = 0;
- else inset = 1;
- }
-
- if(val && (event==FKEY))
- {
- int ct;
- for(ct = 0; ct < ect; ct++){
- if(tagged[ct]->f2 & 32)
- tagged[ct]->f2 &= ~32;
- else
- tagged[ct]->f2 |= 32;
- }
- }
-
- if(val && (event == MIDDLEMOUSE))
- {
- cut = 2;
- searching=0;
- }
- else if(val && (event==LEFTMOUSE || event==RETKEY))
- {
- searching=0;
- }
-
- if(val && (event==ESCKEY || event==RIGHTMOUSE ))
- {
- searching=0;
- cut = 0;
- }
-
- }
-
- /* window coords, no clip with vertices f2 flags set (not used) */
- calc_meshverts_ext_f2();
-
-
- /* Determine the % on wich the loop should be cut */
- getmouseco_areawin(mval);
- v1[0]=(float)mval[0];
- v1[1]=(float)mval[1];
-
- v2[0]=(float)start->v1->xs;
- v2[1]=(float)start->v1->ys;
-
- v3[0]=(float)start->v2->xs;
- v3[1]=(float)start->v2->ys;
-
- rc[0]= v3[0]-v2[0];
- rc[1]= v3[1]-v2[1];
- len= rc[0]*rc[0]+ rc[1]*rc[1];
-
- labda= ( rc[0]*(v1[0]-v2[0]) + rc[1]*(v1[1]-v2[1]) )/len;
-
-
- if(labda<=0.0) labda=0.0;
- else if(labda>=1.0)labda=1.0;
-
- percentcut=labda;
-
- if(start->f2 & 32)
- percentcut = 1.0-percentcut;
-
- if(cut == 2){
- percentcut = 0.5;
- }
-
- if (G.qual & LR_SHIFTKEY){
-
- percentcut = (int)(percentcut*100.0)/100.0;
- }
- else if (G.qual & LR_CTRLKEY)
- percentcut = (int)(percentcut*10.0)/10.0;
-
- outcut = (percentcut*100.0);
-
- /* Build the Header Line */
-
- if(inset)
- sprintf(mesg,"Cut: %0.2f%% ",slen*percentcut);
- else
- sprintf(mesg,"Cut: %0.2f%% ",outcut);
-
-
- if(smooth)
- sprintf(mesg,"%s| (f)lip side | (s)mooth on |",mesg);
- else
- sprintf(mesg,"%s| (f)lip side | (s)mooth off |",mesg);
-
- if(inset)
- sprintf(mesg,"%s (p)roportional on ",mesg);
- else
- sprintf(mesg,"%s (p)roportional off",mesg);
-
- headerprint(mesg);
-
- screen_swapbuffers();
- }
-
- if(cut){
- /* Now that we have selected a cut %, mark the edges for cutting. */
- if(!inset){
-
- for(eed = em->edges.first; eed; eed=eed->next){
- if(percentcut == 1.0)
- percentcut = 0.9999;
- else if(percentcut == 0.0)
- percentcut = 0.0001;
- if(eed->f2 & 8){
- if(eed->f2 & 32)/* Need to offset by a const. (0.5/32768) for consistant roundoff */
- eed->f1 = 32768*(1.0-percentcut - 0.0000153);
- else
- eed->f1 = 32768*(percentcut + 0.0000153);
- }
- }
- }
- /*-------------------------------------*/
-
- if(smooth)
- subdivideflag(8, 0, B_KNIFE | B_PERCENTSUBD | B_SMOOTH); /* B_KNIFE tells subdivide that edgeflags are already set */
- else
- subdivideflag(8, 0, B_KNIFE | B_PERCENTSUBD); /* B_KNIFE tells subdivide that edgeflags are already set */
-
- for(eed = em->edges.first; eed; eed=eed->next){
- if(eed->v1->f & 16) eed->v1->f |= SELECT; //
- else eed->v1->f &= ~SELECT;
-
- if(eed->v2->f & 16) eed->v2->f |= SELECT;
- else eed->v2->f &= ~SELECT;
-
- /* proper edge select state, needed because subdivide still doesnt do it OK */
- if(eed->v1->f & eed->v2->f & SELECT) eed->f |= SELECT;
- else eed->f &= ~SELECT;
- }
- }
- }
- /*----------END Cut Loop-----------------------------*/
-
-
-
- /* Clear flags */
- for(eed = em->edges.first; eed; eed=eed->next){
- eed->f2 &= ~(2|4|8|32|64);
- eed->v1->f &= ~(2|16); // xxx
- eed->v2->f &= ~(2|16);
- }
-
- for(efa= em->faces.first; efa; efa=efa->next){
- efa->f1 &= ~(4|8);
-
- /* proper face select state, needed because subdivide still doesnt do it OK */
- if( faceselectedAND(efa, SELECT) ) efa->f |= SELECT;
- else efa->f &= ~SELECT;
- }
-
- // flushes vertex -> edge -> face selection
- EM_select_flush();
-
- countall();
-
- if(tagged)
- MEM_freeN(tagged);
- if(taggedsrch)
- MEM_freeN(taggedsrch);
- if(percentfacesloop)
- MEM_freeN(percentfacesloop);
-
- /* send event to redraw this window, does header too */
- SetBlenderCursor(SYSCURSOR);
- addqueue(curarea->win, REDRAW, 1);
-
- /* should have check for cancelled (ton) */
- if(mode==LOOP_CUT) BIF_undo_push("Face Loop Subdivide");
- else if(mode==LOOP_SELECT) BIF_undo_push("Select Face Loop");
-
-}
-
-/* ****************************** END LOOPOPERATIONS ********************** */
-
void LoopMenu(){ /* Called by KKey */
short ret;
- ret=pupmenu("Loop/Cut Menu %t|Face Loop Select %x1|Face Loop Cut %x2|"
- "Knife (Exact) %x3|Knife (Midpoints)%x4|");
+ ret=pupmenu("Loop/Cut Menu %t|Loop Cut (CTRL-R)%x2|"
+ "Knife (Exact) %x3|Knife (Midpoints)%x4|Knife (Multicut)%x5");
switch (ret){
- case 1:
- loopoperations(LOOP_SELECT);
- break;
case 2:
- loopoperations(LOOP_CUT);
+ CutEdgeloop(1);
break;
case 3:
KnifeSubdivide(KNIFE_EXACT);
break;
case 4:
KnifeSubdivide(KNIFE_MIDPOINT);
+ break;
+ case 5:
+ KnifeSubdivide(KNIFE_MULTICUT);
+ break;
}
}
diff --git a/source/blender/src/editmesh_mods.c b/source/blender/src/editmesh_mods.c
index 8229f55449f..e09748cf2cc 100644
--- a/source/blender/src/editmesh_mods.c
+++ b/source/blender/src/editmesh_mods.c
@@ -974,6 +974,74 @@ static void edgeloop_select(EditEdge *starteed, int select)
}
}
+/*
+ Almostly exactly the same code as faceloop select
+*/
+static void edgering_select(EditEdge *startedge, int select){
+ EditMesh *em = G.editMesh;
+ EditEdge *eed;
+ EditFace *efa;
+ int looking= 1;
+
+ /* in eed->f1 we put the valence (amount of faces in edge) */
+ /* in eed->f2 we put tagged flag as correct loop */
+ /* in efa->f1 we put tagged flag as correct to select */
+
+ for(eed= em->edges.first; eed; eed= eed->next) {
+ eed->f1= 0;
+ eed->f2= 0;
+ }
+ for(efa= em->faces.first; efa; efa= efa->next) {
+ efa->f1= 0;
+ if(efa->h==0) {
+ efa->e1->f1++;
+ efa->e2->f1++;
+ efa->e3->f1++;
+ if(efa->e4) efa->e4->f1++;
+ }
+ }
+
+ // tag startedge OK
+ startedge->f2= 1;
+
+ while(looking) {
+ looking= 0;
+
+ for(efa= em->faces.first; efa; efa= efa->next) {
+ if(efa->e4 && efa->f1==0) { // not done quad
+ if(efa->e1->f1<=2 && efa->e2->f1<=2 && efa->e3->f1<=2 && efa->e4->f1<=2) { // valence ok
+
+ // if edge tagged, select opposing edge and mark face ok
+ if(efa->e1->f2) {
+ efa->e3->f2= 1;
+ efa->f1= 1;
+ looking= 1;
+ }
+ else if(efa->e2->f2) {
+ efa->e4->f2= 1;
+ efa->f1= 1;
+ looking= 1;
+ }
+ if(efa->e3->f2) {
+ efa->e1->f2= 1;
+ efa->f1= 1;
+ looking= 1;
+ }
+ if(efa->e4->f2) {
+ efa->e2->f2= 1;
+ efa->f1= 1;
+ looking= 1;
+ }
+ }
+ }
+ }
+ }
+
+ /* (de)select the edges */
+ for(eed= em->edges.first; eed; eed= eed->next) {
+ if(eed->f2) EM_select_edge(eed, select);
+ }
+}
/* ***************** MAIN MOUSE SELECTION ************** */
// just to have the functions nice together
@@ -993,8 +1061,14 @@ static void mouse_mesh_loop(void)
if(G.scene->selectmode & SCE_SELECT_FACE) {
faceloop_select(eed, eed->f & SELECT);
}
- else {
- edgeloop_select(eed, eed->f & SELECT);
+ else if(G.scene->selectmode & SCE_SELECT_EDGE) {
+ if(G.qual == (LR_CTRLKEY | LR_ALTKEY) || G.qual == (LR_CTRLKEY | LR_ALTKEY |LR_SHIFTKEY))
+ edgering_select(eed, eed->f & SELECT);
+ else if(G.qual & LR_ALTKEY)
+ edgeloop_select(eed, eed->f & SELECT);
+ }
+ else if(G.scene->selectmode & SCE_SELECT_VERTEX) {
+ edgeloop_select(eed, eed->f & SELECT);
}
/* frontbuffer draw of last selected only */
@@ -1696,7 +1770,7 @@ void editmesh_mark_seam(int clear)
void Edge_Menu() {
short ret;
- ret= pupmenu("Edge Specials%t|Mark Seam %x1|Clear Seam %x2|Rotate Edge CW%x3|Rotate Edge CCW%x4");
+ ret= pupmenu("Edge Specials%t|Mark Seam %x1|Clear Seam %x2|Rotate Edge CW%x3|Rotate Edge CCW%x4|Loopcut%x6|Edge Slide%x5");
switch(ret)
{
@@ -1712,6 +1786,14 @@ void Edge_Menu() {
case 4:
edge_rotate_selected(1);
break;
+ case 5:
+ EdgeSlide(0,0.0);
+ BIF_undo_push("EdgeSlide");
+ break;
+ case 6:
+ CutEdgeloop(1);
+ BIF_undo_push("Loopcut New");
+ break;
}
}
diff --git a/source/blender/src/editmesh_tools.c b/source/blender/src/editmesh_tools.c
index 0f836e5f92f..142678e1369 100644
--- a/source/blender/src/editmesh_tools.c
+++ b/source/blender/src/editmesh_tools.c
@@ -25,7 +25,7 @@
*
* The Original Code is: all of this file.
*
- * Contributor(s): none yet.
+ * Contributor(s): Johnny Matthews.
*
* ***** END GPL/BL DUAL LICENSE BLOCK *****
*/
@@ -46,7 +46,7 @@ editmesh_tool.c: UI called tools for editmesh, geometry changes here, otherwise
#include "MEM_guardedalloc.h"
-
+#include "BMF_Api.h"
#include "DNA_mesh_types.h"
#include "DNA_material_types.h"
#include "DNA_meshdata_types.h"
@@ -59,6 +59,8 @@ editmesh_tool.c: UI called tools for editmesh, geometry changes here, otherwise
#include "BLI_arithb.h"
#include "BLI_editVert.h"
#include "BLI_rand.h"
+#include "BLI_ghash.h"
+#include "BLI_linklist.h"
#include "BKE_depsgraph.h"
#include "BKE_global.h"
@@ -90,11 +92,12 @@ editmesh_tool.c: UI called tools for editmesh, geometry changes here, otherwise
#include "editmesh.h"
+#include "MTC_vectorops.h"
/* local prototypes ---------------*/
void bevel_menu(void);
-
-
+static void free_tagged_edgelist(EditEdge *eed);
+static void free_tagged_facelist(EditFace *efa);
/********* qsort routines *********/
@@ -1098,868 +1101,1068 @@ void fill_mesh(void)
BIF_undo_push("Fill");
}
+/*--------------Edge Based Subdivide------------------*/
+#define EDGENEW 2
+#define EDGEINNER 4
+static void alter_co(float* co,EditEdge *edge,float rad,int beauty){
+ float vec1[3],vec2[3],fac,vec3[3],vec4[4],len,ang;
+
+ if(rad > 0.0) { /* subdivide sphere */
+ Normalise(co);
+ co[0]*= rad;
+ co[1]*= rad;
+ co[2]*= rad;
+ }
+ else if(rad< 0.0) { /* fractal subdivide */
+ fac= rad* VecLenf(edge->v1->co, edge->v2->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());
+ VecAddf(co, co, vec1);
+ }
-/* ******************** SUBDIVIDE ********************************** */
+ if(beauty & B_SMOOTH) {
+ // We are using the 2 ends of the edge vertex normals to
+ // determine the arc for the smooth
+
+ // This figures our smooth radius for this edge
+ ang = acos(MTC_dot3Float(edge->v1->no,edge->v2->no))/2;
+ len = VecLenf(edge->v1->co,edge->v2->co)/2;
+ rad = len/sin(ang);
+
+ // Now find the centerpoint of the smooth radius
+ // Need to calculate and add the offset.
+ //
+ // L1 = v1->co + a v1->no
+ // L2 = v2->co + b v2->no
+ //
+ // Assume they intersect
+ //
+ // Set equal
+ //
+ // v1->co + a v1->no = v2->co + b v2->no
+ //
+ // a v1->no = (v2->co - v1->co) + b v2->no
+ //
+ // Cross v2->no with both sides
+ //
+ // a (v1->no X v2->no) = (v2->co - v1->co) X v2->no
+ // a (vec1) = vec2 X v2->no
+ // a vec1 = vec3
+ // a = length(vec3) / length(vec1)
+ //
+ // Now plug a into L1 = v1->co + a v1->no, this is intersection
+
+ Crossf(vec1,edge->v1->no,edge->v2->no);
+ VecSubf(vec2,edge->v2->co,edge->v1->co);
+ Crossf(vec3,vec2,edge->v2->no);
+ len = VecLength(vec3)/VecLength(vec1);
+
+ VECCOPY(vec4,edge->v1->no);
+ VecMulf(vec4,len);
+ VecAddf(vec1,edge->v1->co,vec4);
+ // vec1 *should* be the smooth center offset.
-static void merge_weights(EditVert * vt, EditVert *vs )
-{
- MDeformWeight *newdw;
- int i,j,done;
- for (j=0; j<vs->totweight; j++){
- done=0;
- /* Is vertex memeber of group */
- /* If so: Change its weight */
- for (i=0; i<vt->totweight; i++){
- if (vt->dw[i].def_nr == vs->dw[j].def_nr)
- { /* taking the maximum makes it independant from order of occurance */
- if (vt->dw[i].weight < vs->dw[j].weight) vt->dw[i].weight = vs->dw[j].weight;
- done=1;
- break;
- }
- }
- /* If not: Add the group and set its weight */
- if (!done){
- newdw = MEM_callocN (sizeof(MDeformWeight)*(vt->totweight+1), "deformWeight");
- if (vt->dw){
- memcpy (newdw, vt->dw, sizeof(MDeformWeight)*vt->totweight);
- MEM_freeN (vt->dw);
- }
- vt->dw=newdw;
- vt->dw[vt->totweight].weight=vs->dw[j].weight;
- vt->dw[vt->totweight].def_nr=vs->dw[j].def_nr;
- vt->totweight++;
- }
- }
+ //VecSubf(co,co,vec1);
+
+ Normalise(co);
+
+ co[0]*= rad;
+ co[1]*= rad;
+ co[2]*= rad;
+
+ //VecAddf(co,co,vec1);
+ }
}
-
-static void set_weights(EditVert * vt, EditVert *vs1,EditVert *vs2,EditVert *vs3,EditVert *vs4 )
-{
-/*
-vt is a new generated vertex with empty deform group information
-vs1..v4 are egde neighbours holding group information
-so let the information ooze into the new one
-*/
- if (vs1) merge_weights(vt,vs1);
- if (vs2) merge_weights(vt,vs2);
- if (vs3) merge_weights(vt,vs3);
- if (vs4) merge_weights(vt,vs4);
+static void flipvertarray(EditVert** arr, short size){
+ EditVert *hold;
+ int i;
+
+ for(i=0;i<size/2;i++){
+ hold = arr[i];
+ arr[i] = arr[size-i-1];
+ arr[size-i-1] = hold;
+ }
}
+static void set_uv_vcol(EditFace *efa, float *co, float *uv, char *col)
+{
+ EditVert *v1,*v2,*v3,*v4;
+ float xn, yn, zn;
+ float t00, t01, t10, t11;
+ float detsh, u, v, l;
+ int fac;
+ short i, j;
+ char *cp0, *cp1, *cp2;
+
+ /* define best projection of face XY, XZ or YZ */
+ xn= fabs(efa->n[0]);
+ yn= fabs(efa->n[1]);
+ zn= fabs(efa->n[2]);
+ if(zn>=xn && zn>=yn) {i= 0; j= 1;}
+ else if(yn>=xn && yn>=zn) {i= 0; j= 2;}
+ else {i= 1; j= 2;}
+
+ /* calculate u and v */
+ v1= efa->v1;
+ v2= efa->v2;
+ v3= efa->v3;
+
+ t00= v3->co[i]-v1->co[i]; t01= v3->co[j]-v1->co[j];
+ t10= v3->co[i]-v2->co[i]; t11= v3->co[j]-v2->co[j];
+
+ detsh= 1.0/(t00*t11-t10*t01); /* potential danger */
+ t00*= detsh; t01*=detsh;
+ t10*=detsh; t11*=detsh;
+
+ u= (co[i]-v3->co[i])*t11-(co[j]-v3->co[j])*t10;
+ v= (co[j]-v3->co[j])*t00-(co[i]-v3->co[i])*t01;
+
+ /* btw; u and v range from -1 to 0 */
+
+ /* interpolate */
+ l= 1.0+u+v;
+
+ /* outside triangle? */
+ if(efa->v4 && l < 0.0) {
+ /* do it all over, but now with vertex 2 replaced with 4 */
+
+ /* calculate u and v */
+ v1= efa->v1;
+ v4= efa->v4;
+ v3= efa->v3;
+
+ t00= v3->co[i]-v1->co[i]; t01= v3->co[j]-v1->co[j];
+ t10= v3->co[i]-v4->co[i]; t11= v3->co[j]-v4->co[j];
+
+ detsh= 1.0/(t00*t11-t10*t01); /* potential danger */
+ t00*= detsh; t01*=detsh;
+ t10*=detsh; t11*=detsh;
+
+ u= (co[i]-v3->co[i])*t11-(co[j]-v3->co[j])*t10;
+ v= (co[j]-v3->co[j])*t00-(co[i]-v3->co[i])*t01;
+
+ /* btw; u and v range from -1 to 0 */
+
+ /* interpolate */
+ l= 1.0+u+v;
+ uv[0] = (l*efa->tf.uv[2][0] - u*efa->tf.uv[0][0] - v*efa->tf.uv[3][0]);
+ uv[1] = (l*efa->tf.uv[2][1] - u*efa->tf.uv[0][1] - v*efa->tf.uv[3][1]);
+
+ cp0= &(efa->tf.col[0]);
+ cp1= &(efa->tf.col[3]);
+ cp2= &(efa->tf.col[2]);
+
+ for(i=0; i<4; i++) {
+ fac= (int)(l*cp2[i] - u*cp0[i] - v*cp1[i]);
+ col[i]= CLAMPIS(fac, 0, 255);
+ }
+ } else {
+ //new = l*vertex3_val - u*vertex1_val - v*vertex2_val;
+ uv[0] = (l*efa->tf.uv[2][0] - u*efa->tf.uv[0][0] - v*efa->tf.uv[1][0]);
+ uv[1] = (l*efa->tf.uv[2][1] - u*efa->tf.uv[0][1] - v*efa->tf.uv[1][1]);
+
+ cp0= &(efa->tf.col[0]);
+ cp1= &(efa->tf.col[1]);
+ cp2= &(efa->tf.col[2]);
+
+ for(i=0; i<4; i++) {
+ fac= (int)(l*cp2[i] - u*cp0[i] - v*cp1[i]);
+ col[i]= CLAMPIS(fac, 0, 255);
+ }
+ }
+}
+static void facecopy(EditFace *source,EditFace *target){
+
+ set_uv_vcol(source,target->v1->co,target->tf.uv[0],(char*)target->tf.col);
+ set_uv_vcol(source,target->v2->co,target->tf.uv[1],(char*)target->tf.col+1);
+ set_uv_vcol(source,target->v3->co,target->tf.uv[2],(char*)target->tf.col+2);
+ if(target->v4){
+ set_uv_vcol(source,target->v4->co,target->tf.uv[3],target->tf.col+3);
+ }
-
-static unsigned int cpack_fact(unsigned int col1, unsigned int col2, float fact)
-{
- char *cp1, *cp2, *cp;
- unsigned int col=0;
- float facti;
-
- facti=1-fact; /*result is (1-fact) * col1 and fact * col2 */
-
- cp1= (char *)&col1;
- cp2= (char *)&col2;
- cp= (char *)&col;
-
- cp[0]= (char)(facti*cp1[0]+fact*cp2[0]);
- cp[1]= (char)(facti*cp1[1]+fact*cp2[1]);
- cp[2]= (char)(facti*cp1[2]+fact*cp2[2]);
- cp[3]= (char)(facti*cp1[3]+fact*cp2[3]);
-
- return col;
+ target->mat_nr = source->mat_nr;
+ target->tf.flag = source->tf.flag;
+ target->tf.transp = source->tf.transp;
+ target->tf.mode = source->tf.mode;
+ target->tf.tile = source->tf.tile;
+ target->tf.unwrap = source->tf.unwrap;
+ target->tf.tpage = source->tf.tpage;
+ target->flag = source->flag;
+
}
-
-static void uv_half(float *uv, float *uv1, float *uv2)
-{
- uv[0]= (uv1[0]+uv2[0])/2.0f;
- uv[1]= (uv1[1]+uv2[1])/2.0f;
-
+static void fill_quad_single(EditFace *efa, struct GHash *gh, int numcuts){
+ EditEdge *cedge;
+ EditVert *v[4], **verts;
+ EditFace *hold;
+ short start, end, left, right, vertsize,i;
+
+ v[0] = efa->v1;
+ v[1] = efa->v2;
+ v[2] = efa->v3;
+ v[3] = efa->v4;
+
+ if(efa->e1->f & SELECT) { cedge = efa->e1; start = 0;}
+ else if(efa->e2->f & SELECT) { cedge = efa->e2; start = 1;}
+ else if(efa->e3->f & SELECT) { cedge = efa->e3; start = 2;}
+ else if(efa->e4->f & SELECT) { cedge = efa->e4; start = 3;}
+
+ // Point verts to the array of new verts for cedge
+ verts = BLI_ghash_lookup(gh, cedge);
+ //This is the index size of the verts array
+ vertsize = numcuts+2;
+
+ // Is the original v1 the same as the first vert on the selected edge?
+ // if not, the edge is running the opposite direction in this face so flip
+ // the array to the correct direction
+
+ if(verts[0] != v[start]){flipvertarray(verts,numcuts+2);}
+ end = (start+1)%4;
+ left = (start+2)%4;
+ right = (start+3)%4;
+
+ /*
+ We should have something like this now
+
+ end start
+ 3 2 1 0
+ |---*---*---|
+ | |
+ | |
+ | |
+ -------------
+ left right
+
+ where start,end,left, right are indexes of EditFace->v1, etc (stored in v)
+ and 0,1,2... are the indexes of the new verts stored in verts
+
+ We will fill this case like this or this depending on even or odd cuts
+
+ |---*---*---| |---*---|
+ | / \ | | / \ |
+ | / \ | | / \ |
+ |/ \| |/ \|
+ ------------- ---------
+ */
+
+ // Make center face
+ if(vertsize % 2 == 0){
+ hold = addfacelist(verts[(vertsize-1)/2],verts[((vertsize-1)/2)+1],v[left],v[right], NULL,NULL);
+ }else{
+ hold = addfacelist(verts[(vertsize-1)/2],v[left],v[right],NULL, NULL,NULL);
+ }
+ facecopy(efa,hold);
+
+ // Make side faces
+ for(i=0;i<(vertsize-1)/2;i++){
+ hold = addfacelist(verts[i],verts[i+1],v[right],NULL,NULL,NULL);
+ facecopy(efa,hold);
+ hold = addfacelist(verts[vertsize-2-i],verts[vertsize-1-i],v[left],NULL,NULL,NULL);
+ facecopy(efa,hold);
+ }
}
-static void uv_fact(float *uv, float *uv1, float *uv2, float fact)
-{
- float facti = 1.0f - fact;
- uv[0] = facti * uv1[0] + fact * uv2[0];
- uv[1] = facti * uv1[1] + fact * uv2[1];
+static void fill_tri_single(EditFace *efa, struct GHash *gh, int numcuts){
+ EditEdge *cedge;
+ EditVert *v[3], **verts;
+ EditFace *hold;
+ short start, end, op, vertsize,i;
+
+ v[0] = efa->v1;
+ v[1] = efa->v2;
+ v[2] = efa->v3;
+
+ if(efa->e1->f & SELECT) { cedge = efa->e1; start = 0;}
+ else if(efa->e2->f & SELECT) { cedge = efa->e2; start = 1;}
+ else if(efa->e3->f & SELECT) { cedge = efa->e3; start = 2;}
+
+ // Point verts to the array of new verts for cedge
+ verts = BLI_ghash_lookup(gh, cedge);
+ //This is the index size of the verts array
+ vertsize = numcuts+2;
+
+ // Is the original v1 the same as the first vert on the selected edge?
+ // if not, the edge is running the opposite direction in this face so flip
+ // the array to the correct direction
+
+ if(verts[0] != v[start]){flipvertarray(verts,numcuts+2);}
+ end = (start+1)%3;
+ op = (start+2)%3;
+
+ /*
+ We should have something like this now
+
+ end start
+ 3 2 1 0
+ |---*---*---|
+ \ |
+ \ |
+ \ |
+ \ |
+ \ |
+ \ |
+ |op
+
+ where start,end,op are indexes of EditFace->v1, etc (stored in v)
+ and 0,1,2... are the indexes of the new verts stored in verts
+
+ We will fill this case like this or this depending on even or odd cuts
+
+ 3 2 1 0
+ |---*---*---|
+ \ \ \ |
+ \ \ \ |
+ \ \ \ |
+ \ \ \|
+ \ \\|
+ \ |
+ |op
+ */
+
+ // Make side faces
+ for(i=0;i<(vertsize-1);i++){
+ hold = addfacelist(verts[i],verts[i+1],v[op],NULL,NULL,NULL);
+ facecopy(efa,hold);
+ }
}
-static void uv_quart(float *uv, float *uv1)
-{
- uv[0]= (uv1[0]+uv1[2]+uv1[4]+uv1[6])/4.0f;
- uv[1]= (uv1[1]+uv1[3]+uv1[5]+uv1[7])/4.0f;
+static void fill_quad_double_op(EditFace *efa, struct GHash *gh, int numcuts){
+ EditEdge *cedge[2];
+ EditVert *v[4], **verts[2];
+ EditFace *hold;
+ short start, end, left, right, vertsize,i;
+
+ v[0] = efa->v1;
+ v[1] = efa->v2;
+ v[2] = efa->v3;
+ v[3] = efa->v4;
+
+ if(efa->e1->f & SELECT) { cedge[0] = efa->e1; cedge[1] = efa->e3; start = 0;}
+ else if(efa->e2->f & SELECT) { cedge[0] = efa->e2; cedge[1] = efa->e4; start = 1;}
+
+ // Point verts[0] and [1] to the array of new verts for cedge[0] and cedge[1]
+ verts[0] = BLI_ghash_lookup(gh, cedge[0]);
+ verts[1] = BLI_ghash_lookup(gh, cedge[1]);
+ //This is the index size of the verts array
+ vertsize = numcuts+2;
+
+ // Is the original v1 the same as the first vert on the selected edge?
+ // if not, the edge is running the opposite direction in this face so flip
+ // the array to the correct direction
+
+ if(verts[0][0] != v[start]){flipvertarray(verts[0],numcuts+2);}
+ end = (start+1)%4;
+ left = (start+2)%4;
+ right = (start+3)%4;
+ if(verts[1][0] != v[left]){flipvertarray(verts[1],numcuts+2);}
+ /*
+ We should have something like this now
+
+ end start
+ 3 2 1 0
+ |---*---*---|
+ | |
+ | |
+ | |
+ |---*---*---|
+ 0 1 2 3
+ left right
+
+ We will fill this case like this or this depending on even or odd cuts
+
+ |---*---*---|
+ | | | |
+ | | | |
+ | | | |
+ |---*---*---|
+ */
+
+ // Make side faces
+ for(i=0;i<vertsize-1;i++){
+ hold = addfacelist(verts[0][i],verts[0][i+1],verts[1][vertsize-2-i],verts[1][vertsize-1-i],NULL,NULL);
+ if(i < vertsize-2){
+ hold->e2->f2 |= EDGEINNER;
+ }
+ facecopy(efa,hold);
+ }
}
-static void face_pin_vertex(EditFace *efa, EditVert *vertex)
-{
- if(efa->v1 == vertex) efa->tf.unwrap |= TF_PIN1;
- else if(efa->v2 == vertex) efa->tf.unwrap |= TF_PIN2;
- else if(efa->v3 == vertex) efa->tf.unwrap |= TF_PIN3;
- else if(efa->v4 && vertex && efa->v4 == vertex) efa->tf.unwrap |= TF_PIN4;
-}
-static int vert_offset(EditFace *efa, EditVert *eve)
-{
- if (efa->v1 == eve)
- return 0;
- if (efa->v2 == eve)
- return 1;
- if (efa->v3 == eve)
- return 2;
- if (efa->v4)
- if (efa->v4 == eve)
- return 3;
- return -1;
+static void fill_quad_double_adj(EditFace *efa, struct GHash *gh, int numcuts){
+ EditEdge *cedge[2];
+ EditVert *v[4], **verts[2];
+ EditFace *hold;
+ short start, start2, vertsize,i;
+
+ v[0] = efa->v1;
+ v[1] = efa->v2;
+ v[2] = efa->v3;
+ v[3] = efa->v4;
+
+ if(efa->e1->f & SELECT && efa->e2->f & SELECT) {cedge[0] = efa->e1; cedge[1] = efa->e2; start = 0; start2 = 1;}
+ if(efa->e2->f & SELECT && efa->e3->f & SELECT) {cedge[0] = efa->e2; cedge[1] = efa->e3; start = 1; start2 = 2;}
+ if(efa->e3->f & SELECT && efa->e4->f & SELECT) {cedge[0] = efa->e3; cedge[1] = efa->e4; start = 2; start2 = 3;}
+ if(efa->e4->f & SELECT && efa->e1->f & SELECT) {cedge[0] = efa->e4; cedge[1] = efa->e1; start = 3; start2 = 0;}
+
+ // Point verts[0] and [1] to the array of new verts for cedge[0] and cedge[1]
+ verts[0] = BLI_ghash_lookup(gh, cedge[0]);
+ verts[1] = BLI_ghash_lookup(gh, cedge[1]);
+ //This is the index size of the verts array
+ vertsize = numcuts+2;
+
+ // Is the original v1 the same as the first vert on the selected edge?
+ // if not, the edge is running the opposite direction in this face so flip
+ // the array to the correct direction
+
+ if(verts[0][0] != v[start]){flipvertarray(verts[0],numcuts+2);}
+ if(verts[1][0] != v[start2]){flipvertarray(verts[1],numcuts+2);}
+ /*
+ We should have something like this now
+
+ end start
+ 3 2 1 0
+ start2 0|---*---*---|
+ | |
+ 1* |
+ | |
+ 2* |
+ | |
+ end2 3|-----------|
+
+ We will fill this case like this or this depending on even or odd cuts
+ |---*---*---|
+ | / / / |
+ * / / |
+ | / / |
+ * / |
+ | / |
+ |-----------|
+ */
+
+ // Make outside tris
+ hold = addfacelist(verts[0][vertsize-2],verts[0][vertsize-1],verts[1][1],NULL,NULL,NULL);
+ facecopy(efa,hold);
+ hold = addfacelist(verts[0][0],verts[1][vertsize-1],v[(start2+2)%4],NULL,NULL,NULL);
+ facecopy(efa,hold);
+ // Make side faces
+
+ for(i=0;i<numcuts;i++){
+ hold = addfacelist(verts[0][i],verts[0][i+1],verts[1][vertsize-1-(i+1)],verts[1][vertsize-1-i],NULL,NULL);
+ facecopy(efa,hold);
+ }
}
-static void set_wuv(int tot, EditFace *efa, int v1, int v2, int v3, int v4, EditFace *efapin)
-{
- /* this weird function only to be used for subdivide, the 'w' in the name has no meaning! */
- float *uv, uvo[4][2];
- unsigned int *col, colo[4], col1, col2;
- int a, v;
-
- /* recover pinning */
- if(efapin){
- efa->tf.unwrap= 0;
- if(efapin->tf.unwrap & TF_PIN1) face_pin_vertex(efa, efapin->v1);
- if(efapin->tf.unwrap & TF_PIN2) face_pin_vertex(efa, efapin->v2);
- if(efapin->tf.unwrap & TF_PIN3) face_pin_vertex(efa, efapin->v3);
- if(efapin->tf.unwrap & TF_PIN4) face_pin_vertex(efa, efapin->v4);
- }
-
- memcpy(uvo, efa->tf.uv, sizeof(uvo));
- uv= efa->tf.uv[0];
- memcpy(colo, efa->tf.col, sizeof(colo));
- col= efa->tf.col;
-
- /*
- Quads and Triangles reuse the same cases numbers, so we migh as well do both in the
- same loop. Especially now that the offsets are calculated and not hardcoded, it's
- much easier to reduce the code size (and make it less buggy).
- */
-
- /* ******************************************** */
- /* */
- /* Numbers corespond to verts (corner points), */
- /* edge->vn's (center edges), the Center */
- /* And the quincunx points of a face */
- /* */
- /* ******************************************** */
-
- /* ******************************************** */
- /* as shown here for quads: */
- /* */
- /* 2 ------- 5 -------- 1 */
- /* | \ / | \ / | */
- /* | 10 | 13 | */
- /* | / \ | / \ | */
- /* 6 ------- 9 -------- 8 */
- /* | \ / | \ / | */
- /* | 11 | 12 | */
- /* | / \ | / \ | */
- /* 3 ------- 7 -------- 4 */
- /* */
- /* ******************************************** */
-
- /* ******************************************** */
- /* and for triangles: */
- /* 1 */
- /* / \ */
- /* / \ */
- /* 5 7 */
- /* / \ */
- /* / \ */
- /* 2 --------- 6 -------- 3 */
- /* */
- /* ******************************************** */
-
- /* ******************************************** */
- /* */
- /* My talents in ascii arts are minimal so the */
- /* drawings don't show all possible subdivision */
- /* just draw them on paper if you need to. */
- /* */
- /* ******************************************** */
-
- for(a=0; a<tot; a++, uv+=2, col++) {
- /* edges that are subdivided, if any */
- EditEdge *e1 = NULL, *e2 = NULL;
-
- if(a==0) v= v1;
- else if(a==1) v= v2;
- else if(a==2) v= v3;
- else v= v4;
-
- if(a==3 && v4==0) break;
-
- switch (v) {
- /* Face corners, direct copy of the UVs and VCol */
- case 1:
- case 2:
- case 3:
- case 4:
- uv[0]= uvo[v-1][0];
- uv[1]= uvo[v-1][1];
- *col= colo[v-1];
- break;
- /* Face sides (cutting an edge) */
- /*
- set the edge pointer accordingly, it's used latter to do the
- actual calculations of the new UV and VCol
- */
- case 5:
- e1 = efapin->e1;
- break;
- case 6:
- e1 = efapin->e2;
- break;
- case 7:
- e1 = efapin->e3;
- break;
- case 8:
- e1 = efapin->e4;
- break;
-
- /* The following applies to Quads only */
-
- /* Quad middle, just used when subdividing a quad as a whole */
- /* (not knife nor loop cut) */
- /* UVs and VCol is just the average of the four corners */
- case 9:
- uv_quart(uv, uvo[0]);
- col1= cpack_fact(colo[1], colo[0], 0.5f);
- col2= cpack_fact(colo[2], colo[3], 0.5f);
- *col= cpack_fact(col1, col2, 0.5f);
- break;
- /* Quad corner cuts */
- /* only when two adjacent edges are subdivided (and no others) */
- /* Set both edge pointers accordingly, used later for calculations */
- case 10: // case test==3 in subdivideflag()
- e1 = efapin->e1;
- e2 = efapin->e2;
- break;
- case 11: // case of test==6
- e1 = efapin->e2;
- e2 = efapin->e3;
- break;
- case 12: // case of test==12
- e1 = efapin->e3;
- e2 = efapin->e4;
- break;
- case 13: // case of test==9
- e1 = efapin->e4;
- e2 = efapin->e1;
- break;
- }
- /* if splitting at least an edge */
- if (e1) {
- float percent;
- int off1, off2;
- /* if splitting two edges */
- if (e2) {
- float uv1[2], uv2[2];
- /*
- UV and VCol is obtained by using the middle ground of the weighted
- average for both edges (weighted with Percent cut flag).
- In a nutshell, the average of the cuts on both edges.
- */
- /* first cut */
- off1 = vert_offset(efapin, e1->v1);
- off2 = vert_offset(efapin, e1->v2);
- percent = e1->f1 / 32768.0f;
- uv_fact(uv1, uvo[off1], uvo[off2], percent);
- col1= cpack_fact(colo[off1], colo[off2], percent);
-
- /* second cut */
- off1 = vert_offset(efapin, e2->v1);
- off2 = vert_offset(efapin, e2->v2);
- percent = e2->f1 / 32768.0f;
- uv_fact(uv2, uvo[off1], uvo[off2], percent);
- col2= cpack_fact(colo[off1], colo[off1], percent);
-
- /* average the two */
- uv_half(uv, uv1, uv2);
- *col= cpack_fact(col1, col2, 0.5f);
- }
- /* or only one */
- else {
- /*
- UV and VCol is obtained by using the weighted average
- of both vertice (weighted with Percent cut flag).
- */
- off1 = vert_offset(efapin, e1->v1);
- off2 = vert_offset(efapin, e1->v2);
- percent = e1->f1 / 32768.0f;
- uv_fact(uv, uvo[off1], uvo[off2], percent);
- *col= cpack_fact(colo[off1], colo[off2], percent);
- }
- }
- }
+static void fill_tri_double(EditFace *efa, struct GHash *gh, int numcuts){
+ EditEdge *cedge[2];
+ EditVert *v[3], **verts[2];
+ EditFace *hold;
+ short start, start2, vertsize,i;
+
+ v[0] = efa->v1;
+ v[1] = efa->v2;
+ v[2] = efa->v3;
+
+ if(efa->e1->f & SELECT && efa->e2->f & SELECT) {cedge[0] = efa->e1; cedge[1] = efa->e2; start = 0; start2 = 1;}
+ if(efa->e2->f & SELECT && efa->e3->f & SELECT) {cedge[0] = efa->e2; cedge[1] = efa->e3; start = 1; start2 = 2;}
+ if(efa->e3->f & SELECT && efa->e1->f & SELECT) {cedge[0] = efa->e3; cedge[1] = efa->e1; start = 2; start2 = 0;}
+
+ // Point verts[0] and [1] to the array of new verts for cedge[0] and cedge[1]
+ verts[0] = BLI_ghash_lookup(gh, cedge[0]);
+ verts[1] = BLI_ghash_lookup(gh, cedge[1]);
+ //This is the index size of the verts array
+ vertsize = numcuts+2;
+
+ // Is the original v1 the same as the first vert on the selected edge?
+ // if not, the edge is running the opposite direction in this face so flip
+ // the array to the correct direction
+
+ if(verts[0][0] != v[start]){flipvertarray(verts[0],numcuts+2);}
+ if(verts[1][0] != v[start2]){flipvertarray(verts[1],numcuts+2);}
+ /*
+ We should have something like this now
+
+ end start
+ 3 2 1 0
+ start2 0|---*---*---|
+ | /
+ 1* /
+ | /
+ 2* /
+ | /
+ end2 3|
+
+ We will fill this case like this or this depending on even or odd cuts
+ |---*---*---|
+ | / / /
+ * / /
+ | / /
+ * /
+ | /
+ |
+ */
+
+ // Make outside tri
+ hold = addfacelist(verts[0][vertsize-2],verts[0][vertsize-1],verts[1][1],NULL,NULL,NULL);
+ facecopy(efa,hold);
+ // Make side faces
+
+ for(i=0;i<numcuts;i++){
+ hold = addfacelist(verts[0][i],verts[0][i+1],verts[1][vertsize-1-(i+1)],verts[1][vertsize-1-i],NULL,NULL);
+ facecopy(efa,hold);
+ }
}
-static EditVert *vert_from_number(EditFace *efa, int nr)
-{
- switch(nr) {
- case 0:
- return 0;
- case 1:
- return efa->v1;
- case 2:
- return efa->v2;
- case 3:
- return efa->v3;
- case 4:
- return efa->v4;
- case 5:
- return efa->e1->vn;
- case 6:
- return efa->e2->vn;
- case 7:
- return efa->e3->vn;
- case 8:
- return efa->e4->vn;
- }
-
- return NULL;
+static void fill_quad_triple(EditFace *efa, struct GHash *gh, int numcuts){
+ EditEdge *cedge[3];
+ EditVert *v[4], **verts[3];
+ EditFace *hold;
+ short start, start2, start3, vertsize, i, repeats;
+
+ v[0] = efa->v1;
+ v[1] = efa->v2;
+ v[2] = efa->v3;
+ v[3] = efa->v4;
+
+ if(!(efa->e1->f & SELECT)) {
+ cedge[0] = efa->e2;
+ cedge[1] = efa->e3;
+ cedge[2] = efa->e4;
+ start = 1;start2 = 2;start3 = 3;
+ }
+ if(!(efa->e2->f & SELECT)) {
+ cedge[0] = efa->e3;
+ cedge[1] = efa->e4;
+ cedge[2] = efa->e1;
+ start = 2;start2 = 3;start3 = 0;
+ }
+ if(!(efa->e3->f & SELECT)) {
+ cedge[0] = efa->e4;
+ cedge[1] = efa->e1;
+ cedge[2] = efa->e2;
+ start = 3;start2 = 0;start3 = 1;
+ }
+ if(!(efa->e4->f & SELECT)) {
+ cedge[0] = efa->e1;
+ cedge[1] = efa->e2;
+ cedge[2] = efa->e3;
+ start = 0;start2 = 1;start3 = 2;
+ }
+ // Point verts[0] and [1] to the array of new verts for cedge[0] and cedge[1]
+ verts[0] = BLI_ghash_lookup(gh, cedge[0]);
+ verts[1] = BLI_ghash_lookup(gh, cedge[1]);
+ verts[2] = BLI_ghash_lookup(gh, cedge[2]);
+ //This is the index size of the verts array
+ vertsize = numcuts+2;
+
+ // Is the original v1 the same as the first vert on the selected edge?
+ // if not, the edge is running the opposite direction in this face so flip
+ // the array to the correct direction
+
+ if(verts[0][0] != v[start]) {flipvertarray(verts[0],numcuts+2);}
+ if(verts[1][0] != v[start2]){flipvertarray(verts[1],numcuts+2);}
+ if(verts[2][0] != v[start3]){flipvertarray(verts[2],numcuts+2);}
+ /*
+ We should have something like this now
+
+ start2
+ 3 2 1 0
+ start3 0|---*---*---|3
+ | |
+ 1* *2
+ | |
+ 2* *1
+ | |
+ 3|-----------|0 start
+
+ We will fill this case like this or this depending on even or odd cuts
+ there are a couple of differences. For odd cuts, there is a tri in the
+ middle as well as 1 quad at the bottom (not including the extra quads
+ for odd cuts > 1
+
+ For even cuts, there is a quad in the middle and 2 quads on the bottom
+
+ they are numbered here for clarity
+
+ 1 outer tris and bottom quads
+ 2 inner tri or quad
+ 3 repeating quads
+
+ |---*---*---*---|
+ |1/ / \ \ 1|
+ |/ 3 / \ 3 \|
+ * / 2 \ *
+ | / \ |
+ |/ \ |
+ *---------------*
+ | 3 |
+ | |
+ *---------------*
+ | |
+ | 1 |
+ | |
+ |---------------|
+
+ |---*---*---*---*---|
+ | 1/ / \ \ 1|
+ | / / \ \ |
+ |/ 3 / \ 3 \|
+ * / \ *
+ | / \ |
+ | / 2 \ |
+ |/ \|
+ *-------------------*
+ | |
+ | 3 |
+ | |
+ *-------------------*
+ | |
+ | 1 |
+ | |
+ *-------------------*
+ | |
+ | 1 |
+ | |
+ |-------------------|
+
+ */
+
+ // Make outside tris
+ hold = addfacelist(verts[0][vertsize-2],verts[0][vertsize-1],verts[1][1],NULL,NULL,NULL);
+ facecopy(efa,hold);
+ hold = addfacelist(verts[1][vertsize-2],verts[1][vertsize-1],verts[2][1],NULL,NULL,NULL);
+ facecopy(efa,hold);
+ // Make bottom quad
+ hold = addfacelist(verts[0][0],verts[0][1],verts[2][vertsize-2],verts[2][vertsize-1],NULL,NULL);
+ facecopy(efa,hold);
+ //If it is even cuts, add the 2nd lower quad
+ if(numcuts % 2 == 0){
+ hold = addfacelist(verts[0][1],verts[0][2],verts[2][vertsize-3],verts[2][vertsize-2],NULL,NULL);
+ facecopy(efa,hold);
+ // Also Make inner quad
+ hold = addfacelist(verts[1][numcuts/2],verts[1][(numcuts/2)+1],verts[2][numcuts/2],verts[0][(numcuts/2)+1],NULL,NULL);
+ facecopy(efa,hold);
+ repeats = (numcuts / 2) -1;
+ } else {
+ // Make inner tri
+ hold = addfacelist(verts[1][(numcuts/2)+1],verts[2][(numcuts/2)+1],verts[0][(numcuts/2)+1],NULL,NULL,NULL);
+ facecopy(efa,hold);
+ repeats = ((numcuts+1) / 2)-1;
+ }
+
+ // cuts for 1 and 2 do not have the repeating quads
+ if(numcuts < 3){repeats = 0;}
+ for(i=0;i<repeats;i++){
+ //Make side repeating Quads
+ hold = addfacelist(verts[1][i+1],verts[1][i+2],verts[0][vertsize-i-3],verts[0][vertsize-i-2],NULL,NULL);
+ facecopy(efa,hold);
+ hold = addfacelist(verts[1][vertsize-i-3],verts[1][vertsize-i-2],verts[2][i+1],verts[2][i+2],NULL,NULL);
+ facecopy(efa,hold);
+ }
+ // Do repeating bottom quads
+ for(i=0;i<repeats;i++){
+ if(numcuts % 2 == 1){
+ hold = addfacelist(verts[0][1+i],verts[0][2+i],verts[2][vertsize-3-i],verts[2][vertsize-2-i],NULL,NULL);
+ } else {
+ hold = addfacelist(verts[0][2+i],verts[0][3+i],verts[2][vertsize-4-i],verts[2][vertsize-3-i],NULL,NULL);
+ }
+ facecopy(efa,hold);
+ }
}
-static void addface_subdiv(EditFace *efa, int val1, int val2, int val3, int val4, EditVert *eve, EditFace *efapin)
-{
- EditFace *w;
- EditVert *v1, *v2, *v3, *v4;
-
- if(val1>=9) v1= eve;
- else v1= vert_from_number(efa, val1);
-
- if(val2>=9) v2= eve;
- else v2= vert_from_number(efa, val2);
-
- if(val3>=9) v3= eve;
- else v3= vert_from_number(efa, val3);
-
- if(val4>=9) v4= eve;
- else v4= vert_from_number(efa, val4);
-
- w= addfacelist(v1, v2, v3, v4, efa, NULL);
- if(w) {
- if(efa->v4) set_wuv(4, w, val1, val2, val3, val4, efapin);
- else set_wuv(3, w, val1, val2, val3, val4, efapin);
- }
+static void fill_quad_quadruple(EditFace *efa, struct GHash *gh, int numcuts,float rad,int beauty){
+ EditVert **verts[4], ***innerverts;
+ short vertsize, i, j;
+ float co[3];
+ EditFace *hold;
+ EditEdge temp;
+ // Point verts[0] and [1] to the array of new verts for cedge[0] and cedge[1]
+ verts[0] = BLI_ghash_lookup(gh, efa->e1);
+ verts[1] = BLI_ghash_lookup(gh, efa->e2);
+ verts[2] = BLI_ghash_lookup(gh, efa->e3);
+ verts[3] = BLI_ghash_lookup(gh, efa->e4);
+
+ //This is the index size of the verts array
+ vertsize = numcuts+2;
+
+ // Is the original v1 the same as the first vert on the selected edge?
+ // if not, the edge is running the opposite direction in this face so flip
+ // the array to the correct direction
+
+ if(verts[0][0] != efa->v1) {flipvertarray(verts[0],numcuts+2);}
+ if(verts[1][0] != efa->v2) {flipvertarray(verts[1],numcuts+2);}
+ if(verts[2][0] == efa->v3) {flipvertarray(verts[2],numcuts+2);}
+ if(verts[3][0] == efa->v4) {flipvertarray(verts[3],numcuts+2);}
+ /*
+ We should have something like this now
+ 1
+
+ 3 2 1 0
+ 0|---*---*---|0
+ | |
+ 1* *1
+ 2 | | 4
+ 2* *2
+ | |
+ 3|---*---*---|3
+ 3 2 1 0
+
+ 3
+ // we will fill a 2 dim array of editvert*s to make filling easier
+ // the innervert order is shown
+
+ 0 0---1---2---3
+ | | | |
+ 1 0---1---2---3
+ | | | |
+ 2 0---1---2---3
+ | | | |
+ 3 0---1---2---3
+
+ */
+ innerverts = MEM_mallocN(sizeof(EditVert*)*(numcuts+2),"quad-quad subdiv inner verts outer array");
+ for(i=0;i<numcuts+2;i++){
+ innerverts[i] = MEM_mallocN(sizeof(EditVert*)*(numcuts+2),"quad-quad subdiv inner verts inner array");
+ }
+ // first row is e1 last row is e3
+ for(i=0;i<numcuts+2;i++){
+ innerverts[0][i] = verts[0][(numcuts+1)-i];
+ innerverts[numcuts+1][i] = verts[2][(numcuts+1)-i];
+ }
+ for(i=1;i<=numcuts;i++){
+ innerverts[i][0] = verts[1][i];
+ innerverts[i][numcuts+1] = verts[3][i];
+ for(j=1;j<=numcuts;j++){
+ co[0] = ((verts[1][i]->co[0] - verts[3][i]->co[0]) * (j /(float)(numcuts+1))) + verts[3][i]->co[0];
+ co[1] = ((verts[1][i]->co[1] - verts[3][i]->co[1]) * (j /(float)(numcuts+1))) + verts[3][i]->co[1];
+ co[2] = ((verts[1][i]->co[2] - verts[3][i]->co[2]) * (j /(float)(numcuts+1))) + verts[3][i]->co[2];
+
+ temp.v1 = innerverts[i][0];
+ temp.v2 = innerverts[i][numcuts+1];
+
+ // Call alter co for things like fractal and smooth
+ alter_co(co,&temp,rad,beauty);
+
+ innerverts[i][(numcuts+1)-j] = addvertlist(co);
+
+ //VECCOPY(innerverts[i][(numcuts+1)-j]->no,nor);
+
+ }
+ }
+ // Fill with faces
+ for(i=0;i<numcuts+1;i++){
+ for(j=0;j<numcuts+1;j++){
+ hold = addfacelist(innerverts[i][j+1],innerverts[i][j],innerverts[i+1][j],innerverts[i+1][j+1],NULL,NULL);
+ hold->e1->f2 = EDGENEW;
+ hold->e2->f2 = EDGENEW;
+ hold->e3->f2 = EDGENEW;
+ hold->e4->f2 = EDGENEW;
+ facecopy(efa,hold);
+ }
+ }
+ // Clean up our dynamic multi-dim array
+ for(i=0;i<numcuts+2;i++){
+ MEM_freeN(innerverts[i]);
+ }
+ MEM_freeN(innerverts);
}
-static float smoothperc= 0.0;
-
-static void smooth_subdiv_vec(float *v1, float *v2, float *n1, float *n2, float *vec)
-{
- float len, fac, nor[3], nor1[3], nor2[3];
-
- VecSubf(nor, v1, v2);
- len= 0.5f*Normalise(nor);
-
- VECCOPY(nor1, n1);
- VECCOPY(nor2, n2);
-
- /* cosine angle */
- fac= nor[0]*nor1[0] + nor[1]*nor1[1] + nor[2]*nor1[2] ;
-
- vec[0]= fac*nor1[0];
- vec[1]= fac*nor1[1];
- vec[2]= fac*nor1[2];
-
- /* cosine angle */
- fac= -nor[0]*nor2[0] - nor[1]*nor2[1] - nor[2]*nor2[2] ;
-
- vec[0]+= fac*nor2[0];
- vec[1]+= fac*nor2[1];
- vec[2]+= fac*nor2[2];
-
- vec[0]*= smoothperc*len;
- vec[1]*= smoothperc*len;
- vec[2]*= smoothperc*len;
+static void fill_tri_triple(EditFace *efa, struct GHash *gh, int numcuts,float rad,int beauty){
+ EditVert **verts[3], ***innerverts;
+ short vertsize, i, j;
+ float co[3];
+ EditFace *hold;
+ EditEdge temp;
+
+ // Point verts[0] and [1] to the array of new verts for cedge[0] and cedge[1]
+ verts[0] = BLI_ghash_lookup(gh, efa->e1);
+ verts[1] = BLI_ghash_lookup(gh, efa->e2);
+ verts[2] = BLI_ghash_lookup(gh, efa->e3);
+
+ //This is the index size of the verts array
+ vertsize = numcuts+2;
+
+ // Is the original v1 the same as the first vert on the selected edge?
+ // if not, the edge is running the opposite direction in this face so flip
+ // the array to the correct direction
+
+ if(verts[0][0] != efa->v1) {flipvertarray(verts[0],numcuts+2);}
+ if(verts[1][0] != efa->v2) {flipvertarray(verts[1],numcuts+2);}
+ if(verts[2][0] != efa->v3) {flipvertarray(verts[2],numcuts+2);}
+ /*
+ We should have something like this now
+ 3
+
+ 3 2 1 0
+ 0|---*---*---|3
+ | /
+ 1 1* *2
+ | /
+ 2* *1 2
+ | /
+ 3|/
+ 0
+
+ we will fill a 2 dim array of editvert*s to make filling easier
+
+ 3
+
+ 0 0---1---2---3---4
+ | / | / |/ | /
+ 1 0---1----2---3
+ 1 | / | / | /
+ 2 0----1---2 2
+ | / | /
+ |/ |/
+ 3 0---1
+ | /
+ |/
+ 4 0
+
+ */
+
+ innerverts = MEM_mallocN(sizeof(EditVert*)*(numcuts+2),"tri-tri subdiv inner verts outer array");
+ for(i=0;i<numcuts+2;i++){
+ innerverts[i] = MEM_mallocN(sizeof(EditVert*)*((numcuts+2)-i),"tri-tri subdiv inner verts inner array");
+ }
+ //top row is e3 backwards
+ for(i=0;i<numcuts+2;i++){
+ innerverts[0][i] = verts[2][(numcuts+1)-i];
+ }
+
+ for(i=1;i<=numcuts+1;i++){
+ //first vert is from e1, last is from e2
+ innerverts[i][0] = verts[0][i];
+ innerverts[i][(numcuts+1)-i] = verts[1][(numcuts+1)-i];
+ for(j=1;j<(numcuts+1)-i;j++){
+ co[0] = ((verts[0][i]->co[0] - verts[1][(numcuts+1)-i]->co[0]) * (j/(float)((numcuts+1)-i))) + verts[1][(numcuts+1)-i]->co[0];
+ co[1] = ((verts[0][i]->co[1] - verts[1][(numcuts+1)-i]->co[1]) * (j/(float)((numcuts+1)-i))) + verts[1][(numcuts+1)-i]->co[1];
+ co[2] = ((verts[0][i]->co[2] - verts[1][(numcuts+1)-i]->co[2]) * (j/(float)((numcuts+1)-i))) + verts[1][(numcuts+1)-i]->co[2];
+
+ temp.v1 = innerverts[i][0];
+ temp.v2 = innerverts[i][(numcuts+1)-i];
+
+ alter_co(co,&temp,rad,beauty);
+
+ innerverts[i][((numcuts+1)-i)-j] = addvertlist(co);
+ //VECCOPY(innerverts[i][((numcuts+1)-i)-j]->no,nor);
+ }
+ }
+
+
+ // Now fill the verts with happy little tris :)
+ for(i=0;i<=numcuts+1;i++){
+ for(j=0;j<(numcuts+1)-i;j++){
+ //We always do the first tri
+ hold = addfacelist(innerverts[i][j+1],innerverts[i][j],innerverts[i+1][j],NULL,NULL,NULL);
+ hold->e1->f2 = EDGENEW;
+ hold->e2->f2 = EDGENEW;
+ hold->e3->f2 = EDGENEW;
+ facecopy(efa,hold);
+ //if there are more to come, we do the 2nd
+ if(j+1 <= numcuts-i){
+ hold = addfacelist(innerverts[i+1][j],innerverts[i+1][j+1],innerverts[i][j+1],NULL,NULL,NULL);
+ facecopy(efa,hold);
+ hold->e1->f2 = EDGENEW;
+ hold->e2->f2 = EDGENEW;
+ hold->e3->f2 = EDGENEW;
+ }
+ }
+ }
+
+ // Clean up our dynamic multi-dim array
+ for(i=0;i<numcuts+2;i++){
+ MEM_freeN(innerverts[i]);
+ }
+ MEM_freeN(innerverts);
}
-static void smooth_subdiv_quad(EditFace *efa, float *vec)
-{
-
- float nor1[3], nor2[3];
- float vec1[3], vec2[3];
- float cent[3];
-
- /* vlr->e1->vn is new vertex inbetween v1 / v2 */
-
- VecMidf(nor1, efa->v1->no, efa->v2->no);
- Normalise(nor1);
- VecMidf(nor2, efa->v3->no, efa->v4->no);
- Normalise(nor2);
-
- smooth_subdiv_vec( efa->e1->vn->co, efa->e3->vn->co, nor1, nor2, vec1);
-
- VecMidf(nor1, efa->v2->no, efa->v3->no);
- Normalise(nor1);
- VecMidf(nor2, efa->v4->no, efa->v1->no);
- Normalise(nor2);
-
- smooth_subdiv_vec( efa->e2->vn->co, efa->e4->vn->co, nor1, nor2, vec2);
-
- VecAddf(vec1, vec1, vec2);
-
- CalcCent4f(cent, efa->v1->co, efa->v2->co, efa->v3->co, efa->v4->co);
- VecAddf(vec, cent, vec1);
+// This function takes an example edge, the current point to create and
+// the total # of points to create, then creates the point and return the
+// editvert pointer to it.
+static EditVert *subdivideedgenum(EditEdge *edge,int curpoint,int totpoint,float rad,int beauty){
+ float co[3];
+ float percent;
+ EditVert *ev;
+
+ if (beauty & (B_PERCENTSUBD) && totpoint == 1){
+ percent=(float)(edge->f1)/32768.0f;
+ co[0] = (edge->v2->co[0]-edge->v1->co[0])*percent+edge->v1->co[0];
+ co[1] = (edge->v2->co[1]-edge->v1->co[1])*percent+edge->v1->co[1];
+ co[2] = (edge->v2->co[2]-edge->v1->co[2])*percent+edge->v1->co[2];
+ } else {
+ co[0] = (edge->v2->co[0]-edge->v1->co[0])*(curpoint/(float)(totpoint+1))+edge->v1->co[0];
+ co[1] = (edge->v2->co[1]-edge->v1->co[1])*(curpoint/(float)(totpoint+1))+edge->v1->co[1];
+ co[2] = (edge->v2->co[2]-edge->v1->co[2])*(curpoint/(float)(totpoint+1))+edge->v1->co[2];
+ }
+
+ alter_co(co,edge,rad,beauty);
+ ev = addvertlist(co);
+ ev->f = edge->v1->f;
+
+ return ev;
}
-void subdivideflag(int flag, float rad, int beauty)
+void esubdivideflag(int flag, float rad, int beauty, int numcuts, int seltype)
{
- EditMesh *em = G.editMesh;
- /* subdivide all with (vertflag & flag) */
- /* if rad>0.0 it's a 'sphere' subdivide */
- /* if rad<0.0 it's a fractal subdivide */
- extern float doublimit;
- EditVert *eve;
- EditEdge *eed, *e1, *e2, *e3, *e4, *nexted;
- EditFace *efa, efapin;
- float fac, vec[3], vec1[3], len1, len2, len3, percent;
- short test;
-
- if(beauty & B_SMOOTH) {
- short perc= 100;
-
- if(button(&perc, 10, 500, "Percentage:")==0) return;
-
- smoothperc= 0.292f*perc/100.0f;
- }
-
- /* edgeflags */
- if((beauty & B_KNIFE)==0) { // knife option sets own flags
- eed= em->edges.first;
- while(eed) {
- if( (eed->v1->f & flag) && (eed->v2->f & flag) ) eed->f2= flag;
- else eed->f2= 0;
- eed= eed->next;
- }
- }
-
- /* if beauty: test for area and clear edge flags of 'ugly' edges */
- if(beauty & B_BEAUTY) {
- efa= em->faces.first;
- while(efa) {
- if( faceselectedAND(efa, flag) ) {
- if(efa->v4) {
-
- /* area */
- len1= AreaQ3Dfl(efa->v1->co, efa->v2->co, efa->v3->co, efa->v4->co);
- if(len1 <= doublimit) {
- efa->e1->f2 = 0;
- efa->e2->f2 = 0;
- efa->e3->f2 = 0;
- efa->e4->f2 = 0;
- }
- else {
- len1= VecLenf(efa->v1->co, efa->v2->co) + VecLenf(efa->v3->co, efa->v4->co);
- len2= VecLenf(efa->v2->co, efa->v3->co) + VecLenf(efa->v1->co, efa->v4->co);
-
- if(len1 < len2) {
- efa->e1->f2 = 0;
- efa->e3->f2 = 0;
- }
- else if(len1 > len2) {
- efa->e2->f2 = 0;
- efa->e4->f2 = 0;
- }
- }
- }
- else {
- /* area */
- len1= AreaT3Dfl(efa->v1->co, efa->v2->co, efa->v3->co);
- if(len1 <= doublimit) {
- efa->e1->f2 = 0;
- efa->e2->f2 = 0;
- efa->e3->f2 = 0;
- }
- else {
- len1= VecLenf(efa->v1->co, efa->v2->co) ;
- len2= VecLenf(efa->v2->co, efa->v3->co) ;
- len3= VecLenf(efa->v3->co, efa->v1->co) ;
-
- if(len1<len2 && len1<len3) {
- efa->e1->f2 = 0;
- }
- else if(len2<len3 && len2<len1) {
- efa->e2->f2 = 0;
- }
- else if(len3<len2 && len3<len1) {
- efa->e3->f2 = 0;
- }
- }
- }
- }
- efa= efa->next;
- }
- }
-
- if(beauty & B_SMOOTH) {
-
- vertexnormals(0); /* no1*/
-
- }
-
- /* make new normal and put in edge, clear flag! needed for face creation part below */
- eed= em->edges.first;
- while(eed) {
- if(eed->f2 & flag) {
- /* for now */
- eed->h &= ~EM_FGON;
-
- /* Subdivide percentage is stored in 1/32768ths in eed->f1 */
- if (beauty & B_PERCENTSUBD) percent=(float)(eed->f1)/32768.0f;
- else {
- eed->f1 = 32768 / 2;
- percent=0.5f;
- }
-
- vec[0]= (1-percent)*eed->v1->co[0] + percent*eed->v2->co[0];
- vec[1]= (1-percent)*eed->v1->co[1] + percent*eed->v2->co[1];
- vec[2]= (1-percent)*eed->v1->co[2] + percent*eed->v2->co[2];
-
- if(rad > 0.0) { /* subdivide sphere */
- Normalise(vec);
- vec[0]*= rad;
- vec[1]*= rad;
- vec[2]*= rad;
- }
- else if(rad< 0.0) { /* fractal subdivide */
- fac= rad* VecLenf(eed->v1->co, eed->v2->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());
- VecAddf(vec, vec, vec1);
- }
-
- if(beauty & B_SMOOTH) {
- smooth_subdiv_vec(eed->v1->co, eed->v2->co, eed->v1->no, eed->v2->no, vec1);
- VecAddf(vec, vec, vec1);
- }
-
- eed->vn= addvertlist(vec);
- eed->vn->f= eed->v1->f;
-
- }
- else eed->vn= 0;
-
- eed->f2= 0; /* needed! */
-
- eed= eed->next;
- }
-
- /* test all faces for subdivide edges, there are 8 or 16 cases (ugh)! */
-
- efa= em->faces.last;
- while(efa) {
-
- efapin= *efa; /* make a copy of efa to recover uv pinning later */
-
- if( faceselectedOR(efa, flag) ) {
- /* for now */
- efa->fgonf= 0;
-
- e1= efa->e1;
- e2= efa->e2;
- e3= efa->e3;
- e4= efa->e4;
-
- test= 0;
- if(e1 && e1->vn) {
- test+= 1;
- e1->f2= 1;
- /* add edges here, to copy correct edge data */
- eed= addedgelist(e1->v1, e1->vn, e1);
- eed= addedgelist(e1->vn, e1->v2, e1);
- set_weights(e1->vn, e1->v1,e1->v2,NULL,NULL);
- }
- if(e2 && e2->vn) {
- test+= 2;
- e2->f2= 1;
- /* add edges here, to copy correct edge data */
- eed= addedgelist(e2->v1, e2->vn, e2);
- eed= addedgelist(e2->vn, e2->v2, e2);
- set_weights(e2->vn, e2->v1,e2->v2,NULL,NULL);
- }
- if(e3 && e3->vn) {
- test+= 4;
- e3->f2= 1;
- /* add edges here, to copy correct edge data */
- eed= addedgelist(e3->v1, e3->vn, e3);
- eed= addedgelist(e3->vn, e3->v2, e3);
- set_weights(e3->vn, e3->v1,e3->v2,NULL,NULL);
- }
- if(e4 && e4->vn) {
- test+= 8;
- e4->f2= 1;
- /* add edges here, to copy correct edge data */
- eed= addedgelist(e4->v1, e4->vn, e4);
- eed= addedgelist(e4->vn, e4->v2, e4);
- set_weights(e4->vn, e4->v1,e4->v2,NULL,NULL);
- }
- if(test) {
- if(efa->v4==0) { /* All the permutations of 3 edges*/
- if((test & 3)==3) addface_subdiv(efa, 2, 2+4, 1+4, 0, 0, &efapin);
- if((test & 6)==6) addface_subdiv(efa, 3, 3+4, 2+4, 0, 0, &efapin);
- if((test & 5)==5) addface_subdiv(efa, 1, 1+4, 3+4, 0, 0, &efapin);
-
- if(test==7) { /* four new faces, old face renews */
- efa->v1= e1->vn;
- efa->v2= e2->vn;
- efa->v3= e3->vn;
- set_wuv(3, efa, 1+4, 2+4, 3+4, 0, &efapin);
- }
- else if(test==3) {
- addface_subdiv(efa, 1+4, 2+4, 3, 0, 0, &efapin);
- efa->v2= e1->vn;
- set_wuv(3, efa, 1, 1+4, 3, 0, &efapin);
- }
- else if(test==6) {
- addface_subdiv(efa, 2+4, 3+4, 1, 0, 0, &efapin);
- efa->v3= e2->vn;
- set_wuv(3, efa, 1, 2, 2+4, 0, &efapin);
- }
- else if(test==5) {
- addface_subdiv(efa, 3+4, 1+4, 2, 0, 0, &efapin);
- efa->v1= e3->vn;
- set_wuv(3, efa, 3+4, 2, 3, 0, &efapin);
- }
- else if(test==1) {
- addface_subdiv(efa, 1+4, 2, 3, 0, 0, &efapin);
- efa->v2= e1->vn;
- set_wuv(3, efa, 1, 1+4, 3, 0, &efapin);
- }
- else if(test==2) {
- addface_subdiv(efa, 2+4, 3, 1, 0, 0, &efapin);
- efa->v3= e2->vn;
- set_wuv(3, efa, 1, 2, 2+4, 0, &efapin);
- }
- else if(test==4) {
- addface_subdiv(efa, 3+4, 1, 2, 0, 0, &efapin);
- efa->v1= e3->vn;
- set_wuv(3, efa, 3+4, 2, 3, 0, &efapin);
- }
- efa->e1= addedgelist(efa->v1, efa->v2, NULL);
- efa->e2= addedgelist(efa->v2, efa->v3, NULL);
- efa->e3= addedgelist(efa->v3, efa->v1, NULL);
-
- }
- else { /* All the permutations of 4 faces */
- if(test==15) {
- /* add a new point in center */
- CalcCent4f(vec, efa->v1->co, efa->v2->co, efa->v3->co, efa->v4->co);
-
- if(beauty & B_SMOOTH) {
- smooth_subdiv_quad(efa, vec); /* adds */
- }
- eve= addvertlist(vec);
- set_weights(eve, efa->v1,efa->v2,efa->v3,efa->v4);
- eve->f |= flag;
-
- addface_subdiv(efa, 2, 2+4, 9, 1+4, eve, &efapin);
- addface_subdiv(efa, 3, 3+4, 9, 2+4, eve, &efapin);
- addface_subdiv(efa, 4, 4+4, 9, 3+4, eve, &efapin);
-
- efa->v2= e1->vn;
- efa->v3= eve;
- efa->v4= e4->vn;
- set_wuv(4, efa, 1, 1+4, 9, 4+4, &efapin);
- }
- else {
- if(((test & 3)==3)&&(test!=3)) addface_subdiv(efa, 1+4, 2, 2+4, 0, 0, &efapin);
- if(((test & 6)==6)&&(test!=6)) addface_subdiv(efa, 2+4, 3, 3+4, 0, 0, &efapin);
- if(((test & 12)==12)&&(test!=12)) addface_subdiv(efa, 3+4, 4, 4+4, 0, 0, &efapin);
- if(((test & 9)==9)&&(test!=9)) addface_subdiv(efa, 4+4, 1, 1+4, 0, 0, &efapin);
-
- if(test==1) { /* Edge 1 has new vert */
- addface_subdiv(efa, 1+4, 2, 3, 0, 0, &efapin);
- addface_subdiv(efa, 1+4, 3, 4, 0, 0, &efapin);
- efa->v2= e1->vn;
- efa->v3= efa->v4;
- efa->v4= 0;
- set_wuv(4, efa, 1, 1+4, 4, 0, &efapin);
- }
- else if(test==2) { /* Edge 2 has new vert */
- addface_subdiv(efa, 2+4, 3, 4, 0, 0, &efapin);
- addface_subdiv(efa, 2+4, 4, 1, 0, 0, &efapin);
- efa->v3= e2->vn;
- efa->v4= 0;
- set_wuv(4, efa, 1, 2, 2+4, 0, &efapin);
- }
- else if(test==4) { /* Edge 3 has new vert */
- addface_subdiv(efa, 3+4, 4, 1, 0, 0, &efapin);
- addface_subdiv(efa, 3+4, 1, 2, 0, 0, &efapin);
- efa->v1= efa->v2;
- efa->v2= efa->v3;
- efa->v3= e3->vn;
- efa->v4= 0;
- set_wuv(4, efa, 2, 3, 3+4, 0, &efapin);
- }
- else if(test==8) { /* Edge 4 has new vert */
- addface_subdiv(efa, 4+4, 1, 2, 0, 0, &efapin);
- addface_subdiv(efa, 4+4, 2, 3, 0, 0, &efapin);
- efa->v1= efa->v3;
- efa->v2= efa->v4;
- efa->v3= e4->vn;
- efa->v4= 0;
- set_wuv(4, efa, 3, 4, 4+4, 0, &efapin);
- }
- else if(test==3) { /*edge 1&2 */
- /* make new vert in center of new edge */
- vec[0]=(e1->vn->co[0]+e2->vn->co[0])/2;
- vec[1]=(e1->vn->co[1]+e2->vn->co[1])/2;
- vec[2]=(e1->vn->co[2]+e2->vn->co[2])/2;
- eve= addvertlist(vec);
- set_weights(eve, e1->vn,e2->vn,NULL,NULL);
- eve->f |= flag;
- /* Add new faces */
- addface_subdiv(efa, 4, 10, 2+4, 3, eve, &efapin);
- addface_subdiv(efa, 4, 1, 1+4, 10, eve, &efapin);
- /* orig face becomes small corner */
- efa->v1=e1->vn;
- //efa->v2=efa->v2;
- efa->v3=e2->vn;
- efa->v4=eve;
-
- set_wuv(4, efa, 1+4, 2, 2+4, 10, &efapin);
- }
- else if(test==6) { /* 2&3 */
- /* make new vert in center of new edge */
- vec[0]=(e2->vn->co[0]+e3->vn->co[0])/2;
- vec[1]=(e2->vn->co[1]+e3->vn->co[1])/2;
- vec[2]=(e2->vn->co[2]+e3->vn->co[2])/2;
- eve= addvertlist(vec);
- set_weights(eve, e2->vn,e3->vn,NULL,NULL);
- eve->f |= flag;
- /*New faces*/
- addface_subdiv(efa, 1, 11, 3+4, 4, eve, &efapin);
- addface_subdiv(efa, 1, 2, 2+4, 11, eve, &efapin);
- /* orig face becomes small corner */
- efa->v1=e2->vn;
- efa->v2=efa->v3;
- efa->v3=e3->vn;
- efa->v4=eve;
-
- set_wuv(4, efa, 2+4, 3, 3+4, 11, &efapin);
- }
- else if(test==12) { /* 3&4 */
- /* make new vert in center of new edge */
- vec[0]=(e3->vn->co[0]+e4->vn->co[0])/2;
- vec[1]=(e3->vn->co[1]+e4->vn->co[1])/2;
- vec[2]=(e3->vn->co[2]+e4->vn->co[2])/2;
- eve= addvertlist(vec);
- set_weights(eve, e3->vn,e4->vn,NULL,NULL);
- eve->f |= flag;
- /*New Faces*/
- addface_subdiv(efa, 2, 12, 4+4, 1, eve, &efapin);
- addface_subdiv(efa, 2, 3, 3+4, 12, eve, &efapin);
- /* orig face becomes small corner */
- efa->v1=e3->vn;
- efa->v2=efa->v4;
- efa->v3=e4->vn;
- efa->v4=eve;
-
- set_wuv(4, efa, 3+4, 4, 4+4, 12, &efapin);
- }
- else if(test==9) { /* 4&1 */
- /* make new vert in center of new edge */
- vec[0]=(e1->vn->co[0]+e4->vn->co[0])/2;
- vec[1]=(e1->vn->co[1]+e4->vn->co[1])/2;
- vec[2]=(e1->vn->co[2]+e4->vn->co[2])/2;
- eve= addvertlist(vec);
- set_weights(eve, e1->vn,e4->vn,NULL,NULL);
- eve->f |= flag;
- /*New Faces*/
- addface_subdiv(efa, 3, 13, 1+4, 2, eve, &efapin);
- addface_subdiv(efa, 3, 4, 4+4,13, eve, &efapin);
- /* orig face becomes small corner */
- efa->v2=efa->v1;
- efa->v1=e4->vn;
- efa->v3=e1->vn;
- efa->v4=eve;
-
- set_wuv(4, efa, 4+4, 1, 1+4, 13, &efapin);
- }
- else if(test==5) { /* 1&3 */
- addface_subdiv(efa, 1+4, 2, 3, 3+4, 0, &efapin);
- efa->v2= e1->vn;
- efa->v3= e3->vn;
- set_wuv(4, efa, 1, 1+4, 3+4, 4, &efapin);
- }
- else if(test==10) { /* 2&4 */
- addface_subdiv(efa, 2+4, 3, 4, 4+4, 0, &efapin);
- efa->v3= e2->vn;
- efa->v4= e4->vn;
- set_wuv(4, efa, 1, 2, 2+4, 4+4, &efapin);
- }/* Unfortunately, there is no way to avoid tris on 1 or 3 edges*/
- else if(test==7) { /*1,2&3 */
- addface_subdiv(efa, 1+4, 2+4, 3+4, 0, 0, &efapin);
- efa->v2= e1->vn;
- efa->v3= e3->vn;
- set_wuv(4, efa, 1, 1+4, 3+4, 4, &efapin);
- }
-
- else if(test==14) { /* 2,3&4 */
- addface_subdiv(efa, 2+4, 3+4, 4+4, 0, 0, &efapin);
- efa->v3= e2->vn;
- efa->v4= e4->vn;
- set_wuv(4, efa, 1, 2, 2+4, 4+4, &efapin);
- }
- else if(test==13) {/* 1,3&4 */
- addface_subdiv(efa, 3+4, 4+4, 1+4, 0, 0, &efapin);
- efa->v4= e3->vn;
- efa->v1= e1->vn;
- set_wuv(4, efa, 1+4, 2, 3, 3+4, &efapin);
- }
- else if(test==11) { /* 1,2,&4 */
- addface_subdiv(efa, 4+4, 1+4, 2+4, 0, 0, &efapin);
- efa->v1= e4->vn;
- efa->v2= e2->vn;
- set_wuv(4, efa, 4+4, 2+4, 3, 4, &efapin);
- }
- }
- efa->e1= addedgelist(efa->v1, efa->v2, NULL);
- efa->e2= addedgelist(efa->v2, efa->v3, NULL);
- if(efa->v4) efa->e3= addedgelist(efa->v3, efa->v4, NULL);
- else efa->e3= addedgelist(efa->v3, efa->v1, NULL);
- if(efa->v4) efa->e4= addedgelist(efa->v4, efa->v1, NULL);
- else efa->e4= NULL;
- }
- }
- }
- efa= efa->prev;
- }
-
- /* remove all old edges, if needed make new ones */
- eed= em->edges.first;
- while(eed) {
- nexted= eed->next;
- if( eed->vn ) {
- eed->vn->f |= 16;
- if(eed->f2==0) { /* not used in face */
- addedgelist(eed->v1, eed->vn, eed);
- addedgelist(eed->vn, eed->v2, eed);
- }
- remedge(eed);
- free_editedge(eed);
+ EditMesh *em = G.editMesh;
+ EditFace *ef;
+ EditEdge *eed, *cedge;
+ EditVert **templist;
+ struct GHash *gh;
+ int i,edgecount,facetype;
+ short cuttype=0;
+
+ //Set faces f1 to 0 cause we need it later
+
+ for(ef=em->faces.first;ef;ef = ef->next){
+ ef->f1 = 0;
+ }
+ for(eed = em->edges.first;eed;eed = eed->next){
+ //Flush vertext flags upward to the edges
+ //if(eed->f & flag && eed->v1->f == eed->v2->f){
+ // eed->f |= eed->v1->f;
+ // }
+ eed->f2 = 0;
+ }
+ // We store an array of verts for each edge that is subdivided,
+ // we put this array as a value in a ghash which is keyed by the EditEdge*
+
+ gh = BLI_ghash_new(BLI_ghashutil_ptrhash, BLI_ghashutil_ptrcmp);
+
+ // If we are knifing, We only need the selected edges that were cut, so deselect if it was not cut
+ if(beauty & B_KNIFE) {
+ for(eed= em->edges.first;eed;eed=eed->next){
+ if( eed->f1 == 0 ){
+ EM_select_edge(eed,0);
+ }
}
- eed= nexted;
- }
-
- /* since this is all on vertex level, flush vertex selection */
- EM_select_flush();
+ }
+ // So for each edge, if it is selected, we allocate an array of size cuts+2
+ // so we can have a place for the v1, the new verts and v2
+ for(eed=em->edges.first;eed;eed = eed->next){
+ if(eed->f & flag){
+ templist = MEM_mallocN(sizeof(EditVert*)*(numcuts+2),"vertlist");
+ templist[0] = eed->v1;
+ for(i=0;i<numcuts;i++){
+ // This function creates the new vert and returns it back
+ // to the array
+ templist[i+1] = subdivideedgenum(eed,i+1,numcuts,rad,beauty);
+ //while we are here, we can copy edge info from the original edge
+ cedge = addedgelist(templist[i],templist[i+1],eed);
+ // Also set the edge f2 to EDGENEW so that we can use this info later
+ cedge->f2 = EDGENEW;
+ }
+ templist[i+1] = eed->v2;
+ //Do the last edge too
+ cedge = addedgelist(templist[i],templist[i+1],eed);
+ cedge->f2 = EDGENEW;
+ // Now that the edge is subdivided, we can put its verts in the ghash
+ BLI_ghash_insert(gh, eed, templist);
+ }
+ }
+ vertexnormals(0);
+ // Now for each face in the mesh we need to figure out How many edges were cut
+ // and which filling method to use for that face
+ for(ef = em->faces.first;ef;ef = ef->next){
+ edgecount = 0;
+ facetype = 3;
+ if(ef->e1->f & flag) {edgecount++;}
+ if(ef->e2->f & flag) {edgecount++;}
+ if(ef->e3->f & flag) {edgecount++;}
+ if(ef->v4){
+ facetype = 4;
+ if(ef->e4->f & flag){edgecount++;}
+ }
+ if(facetype == 4){
+ switch(edgecount){
+ case 0: break;
+ case 1: ef->f1 = SELECT;
+ fill_quad_single(ef, gh, numcuts);
+ break;
+ case 2: ef->f1 = SELECT;
+ // if there are 2, we check if edge 1 and 3 are either both on or off that way
+ // we can tell if the selected pair is Adjacent or Opposite of each other
+ if((ef->e1->f & flag && ef->e3->f & flag) ||
+ (ef->e2->f & flag && ef->e4->f & flag)){
+ fill_quad_double_op(ef, gh, numcuts);
+ }else{
+ //printf("adj\n");
+ fill_quad_double_adj(ef, gh, numcuts);
+ }
+ break;
+ case 3: ef->f1 = SELECT;
+ fill_quad_triple(ef, gh, numcuts);
+ break;
+ case 4: ef->f1 = SELECT;
+ fill_quad_quadruple(ef, gh, numcuts,rad,beauty);
+ break;
+ }
+ } else {
+ switch(edgecount){
+ case 0: break;
+ case 1: ef->f1 = SELECT;
+ fill_tri_single(ef, gh, numcuts);
+ break;
+ case 2: ef->f1 = SELECT;
+ fill_tri_double(ef, gh, numcuts);
+ break;
+ case 3: ef->f1 = SELECT;
+ fill_tri_triple(ef, gh, numcuts,rad,beauty);
+ break;
+ }
+ }
+ }
+
+ // Delete Old Faces
+ free_tagged_facelist(em->faces.first);
+ //Delete Old Edges
+ for(eed = em->edges.first;eed;eed = eed->next){
+ if(BLI_ghash_haskey(gh,eed)){
+ eed->f1 = SELECT;
+ } else {
+ eed->f1 = 0;
+ }
+ }
+ free_tagged_edgelist(em->edges.first);
+
+ if(seltype == 0){
+ for(eed = em->edges.first;eed;eed = eed->next){
+ if(eed->f2 & EDGENEW){
+ eed->f |= flag;
+ EM_select_edge(eed,1);
+ }else{
+ eed->f &= !flag;
+ EM_select_edge(eed,0);
+ }
+ }
+ } else if (seltype == 1){
+ for(eed = em->edges.first;eed;eed = eed->next){
+ if(eed->f2 & EDGEINNER){
+ eed->f |= flag;
+ EM_select_edge(eed,1);
+ }else{
+ eed->f &= !flag;
+ EM_select_edge(eed,0);
+ }
+ }
+ }
+ // Free the ghash and call MEM_freeN on all the value entries to return
+ // that memory
+ BLI_ghash_free(gh, NULL, MEM_freeN);
+
recalc_editnormals();
-
countall();
allqueue(REDRAWVIEW3D, 0);
DAG_object_flush_update(G.scene, G.obedit, OB_RECALC_DATA);
}
+
+
static int count_selected_edges(EditEdge *ed)
{
int totedge = 0;
@@ -2147,7 +2350,6 @@ if(efa1->v1== *v2) {
else {
*v3= *v4= NULL;
- printf("error in givequadverts()\n");
return;
}
@@ -3858,4 +4060,1268 @@ void bevel_menu()
/* *********** END BEVEL *********/
+typedef struct SlideVert {
+ EditEdge *up,*down;
+ EditVert origvert;
+} SlideVert;
+
+// This passes a ghash to the ghash free function so we can use it pseudo-recursively later
+void freeGHash(GHash *g){
+ BLI_ghash_free(g,NULL,NULL);
+ return;
+}
+
+void EdgeSlide(short immediate, float imperc){
+ EditMesh *em = G.editMesh;
+ EditFace *efa;
+ EditEdge *eed,*first=NULL,*last=NULL, *temp = NULL;
+ EditVert *ev;
+ LinkNode *edgelist = NULL, *vertlist=NULL, *look;
+ int i = 0,j;
+ char str[128];
+ int numsel,numadded=0,timesthrough = 0,vertsel=0,prop=1,side=1;
+ short event,draw=1;
+ GHash *vertgh;
+ SlideVert *tempsv;
+ float perc = 0, percp = 0;
+ short mval[2],mvalo[2];
+
+ mvalo[0] = -1;mvalo[1] = -1;
+ numsel =0;
+
+
+
+ // Get number of selected edges and clear some flags
+ for(eed=em->edges.first;eed;eed=eed->next){
+ eed->f1 = 0;
+ eed->f2 = 0;
+ if(eed->f & SELECT) numsel++;
+ }
+
+ for(ev=em->verts.first;ev;ev=ev->next){
+ ev->f1 = 0;
+ }
+
+ //Make sure each edge only has 2 faces
+ // make sure loop doesn't cross face
+ for(efa=em->faces.first;efa;efa=efa->next){
+ int ct = 0;
+ if(efa->e1->f & SELECT){
+ ct++;
+ efa->e1->f1++;
+ if(efa->e1->f1 > 2){
+ okee("3+ face edge - Stopping");
+ return;
+ }
+ }
+ if(efa->e2->f & SELECT){
+ ct++;
+ efa->e2->f1++;
+ if(efa->e2->f1 > 2){
+ okee("3+ face edge - Stopping");
+ return;
+ }
+ }
+ if(efa->e3->f & SELECT){
+ ct++;
+ efa->e3->f1++;
+ if(efa->e3->f1 > 2){
+ okee("3+ face edge - Stopping");
+ return;
+ }
+ }
+ if(efa->e4 && efa->e4->f & SELECT){
+ ct++;
+ efa->e4->f1++;
+ if(efa->e4->f1 > 2){
+ okee("3+ face edge - Stopping");
+ return;
+ }
+ }
+ // Make sure loop is not 2 edges of same face
+ if(ct > 1){
+ okee("loop crosses itself - Stopping");
+ return;
+ }
+ }
+ // Get # of selected verts
+ for(ev=em->verts.first;ev;ev=ev->next){
+ if(ev->f & SELECT) vertsel++;
+ }
+
+ // Test for multiple segments
+ if(vertsel > numsel+1){
+ okee("Was not a single edge loop - Stopping");
+ return;
+ }
+
+ // Get the edgeloop in order - mark f1 with SELECT once added
+ for(eed=em->edges.first;eed;eed=eed->next){
+ if((eed->f & SELECT) && !(eed->f1 & SELECT)){
+ // If this is the first edge added, just put it in
+ if(!edgelist){
+ BLI_linklist_prepend(&edgelist,eed);
+ numadded++;
+ first = eed;
+ last = eed;
+ eed->f1 = SELECT;
+ } else {
+ if((eed->v1 == last->v1 || eed->v1 == last->v2) ||
+ (eed->v2 == last->v1 || eed->v2 == last->v2) ){
+ BLI_linklist_append(&edgelist,eed);
+ eed->f1 = SELECT;
+ numadded++;
+ last = eed;
+ } else if((eed->v1 == first->v1 || eed->v1 == first->v2) ||
+ ( eed->v2 == first->v1 || eed->v2 == first->v2) ){
+ BLI_linklist_prepend(&edgelist,eed);
+ eed->f1 = SELECT;
+ numadded++;
+ first = eed;
+ }
+ }
+ }
+ if(eed->next == NULL && numadded != numsel){
+ eed=em->edges.first;
+ timesthrough++;
+ }
+
+ // It looks like there was an unexpected case - Hopefully should not happen
+ if(timesthrough >= numsel*2){
+ BLI_linklist_free(edgelist,NULL);
+ okee("could not order loop - Stopping");
+ return;
+ }
+ }
+
+ // Put the verts in order in a linklist
+ look = edgelist;
+ while(look){
+ eed = look->link;
+ if(!vertlist){
+ if(look->next){
+ temp = look->next->link;
+
+ //This is the first entry takes care of extra vert
+ if(eed->v1 != temp->v1 && eed->v1 != temp->v2){
+ BLI_linklist_append(&vertlist,eed->v1);
+ eed->v1->f1 = 1;
+ } else {
+ BLI_linklist_append(&vertlist,eed->v2);
+ eed->v2->f1 = 1;
+ }
+ } else {
+ //This is the case that we only have 1 edge
+ BLI_linklist_append(&vertlist,eed->v1);
+ eed->v1->f1 = 1;
+ }
+ }
+ // for all the entries
+ if(eed->v1->f1 != 1){
+ BLI_linklist_append(&vertlist,eed->v1);
+ eed->v1->f1 = 1;
+ } else if(eed->v2->f1 != 1){
+ BLI_linklist_append(&vertlist,eed->v2);
+ eed->v2->f1 = 1;
+ }
+ look = look->next;
+ }
+
+ // populate the SlideVerts
+
+ vertgh = BLI_ghash_new(BLI_ghashutil_ptrhash, BLI_ghashutil_ptrcmp);
+ look = vertlist;
+ while(look){
+ i=0;
+ j=0;
+ ev = look->link;
+ tempsv = (struct SlideVert*)MEM_mallocN(sizeof(struct SlideVert),"SlideVert");
+ tempsv->up = NULL;
+ tempsv->down = NULL;
+ tempsv->origvert.co[0] = ev->co[0];
+ tempsv->origvert.co[1] = ev->co[1];
+ tempsv->origvert.co[2] = ev->co[2];
+ tempsv->origvert.no[0] = ev->no[0];
+ tempsv->origvert.no[1] = ev->no[1];
+ tempsv->origvert.no[2] = ev->no[2];
+ // i is total edges that vert is on
+ // j is total selected edges that vert is on
+
+ for(eed=em->edges.first;eed;eed=eed->next){
+ if(eed->v1 == ev || eed->v2 == ev){
+ i++;
+ if(eed->f & SELECT){
+ j++;
+ }
+ }
+ }
+ // If the vert is in the middle of an edge loop, it touches 2 selected edges and 2 unselected edges
+ if(i == 4 && j == 2){
+ for(eed=em->edges.first;eed;eed=eed->next){
+ if(eed->v1 == ev || eed->v2 == ev){
+ if(!(eed->f & SELECT)){
+ if(!tempsv->up){
+ tempsv->up = eed;
+ } else if (!(tempsv->down)){
+ tempsv->down = eed;
+ }
+ }
+ }
+ }
+ }
+ // If it is on the end of the loop, it touches 1 selected and as least 2 more unselected
+ if(i >= 3 && j == 1){
+ for(eed=em->edges.first;eed;eed=eed->next){
+ if((eed->v1 == ev || eed->v2 == ev) && eed->f & SELECT){
+ for(efa = em->faces.first;efa;efa=efa->next){
+ if((efa->e1 == eed || efa->e2 == eed) || (efa->e3 == eed || (efa->e4 && efa->e4 == eed))){
+ if((efa->e1->v1 == ev || efa->e1->v2 == ev) && efa->e1 != eed){
+ if(!tempsv->up){
+ tempsv->up = efa->e1;
+ } else if (!(tempsv->down)){
+ tempsv->down = efa->e1;
+ }
+ }
+ if((efa->e2->v1 == ev || efa->e2->v2 == ev) && efa->e2 != eed){
+ if(!tempsv->up){
+ tempsv->up = efa->e2;
+ } else if (!(tempsv->down)){
+ tempsv->down = efa->e2;
+ }
+ }
+ if((efa->e3->v1 == ev || efa->e3->v2 == ev) && efa->e3 != eed){
+ if(!tempsv->up){
+ tempsv->up = efa->e3;
+ } else if (!(tempsv->down)){
+ tempsv->down = efa->e3;
+ }
+ }
+ if(efa->e4){
+ if((efa->e4->v1 == ev || efa->e4->v2 == ev) && efa->e4 != eed){
+ if(!tempsv->up){
+ tempsv->up = efa->e4;
+ } else if (!(tempsv->down)){
+ tempsv->down = efa->e4;
+ }
+ }
+ }
+
+ }
+ }
+ }
+ }
+ }
+ if(i > 4 && j == 2){
+ BLI_ghash_free(vertgh,NULL,MEM_freeN);
+ BLI_linklist_free(vertlist,NULL);
+ BLI_linklist_free(edgelist,NULL);
+ return;
+ }
+ BLI_ghash_insert(vertgh,ev,tempsv);
+
+ look = look->next;
+ }
+
+ // make sure the UPs nad DOWNs are 'faceloops'
+
+ look = vertlist;
+ while(look){
+ SlideVert *sv;
+ if(look->next != NULL){
+ tempsv = BLI_ghash_lookup(vertgh,(EditVert*)look->link);
+ sv = BLI_ghash_lookup(vertgh,(EditVert*)look->next->link);
+ if(!sharesFace(tempsv->up,sv->up)){
+ EditEdge *swap;
+ swap = sv->up;
+ sv->up = sv->down;
+ sv->down = swap;
+ }
+ }
+ look = look->next;
+ }
+
+ // we should have enough info now to slide
+ //persp(PERSP_WIN);
+ //glDrawBuffer(GL_FRONT);
+ while(draw){
+ if(perc == percp){
+ PIL_sleep_ms(10);
+ } else {
+ //Adjust Edgeloop
+ if(immediate){
+ perc = imperc;
+ }
+ percp = perc;
+ if(perc >=0){
+ if(prop){
+ look = vertlist;
+ while(look){
+ EditVert *tempev;
+ ev = look->link;
+ tempsv = BLI_ghash_lookup(vertgh,ev);
+
+ if(tempsv->up->v1 == ev){
+ tempev = tempsv->up->v2;
+ } else {
+ tempev = tempsv->up->v1;
+ }
+
+ ev->co[0] = ((tempsv->origvert.co[0]-tempev->co[0])*(1-fabs(perc))) + tempev->co[0];
+ ev->co[1] = ((tempsv->origvert.co[1]-tempev->co[1])*(1-fabs(perc))) + tempev->co[1];
+ ev->co[2] = ((tempsv->origvert.co[2]-tempev->co[2])*(1-fabs(perc))) + tempev->co[2];
+
+ look = look->next;
+ }
+ }
+ else {
+ //Non prop code
+ }
+ } else {
+ if(prop){
+ look = vertlist;
+ while(look){
+ EditVert *tempev;
+ ev = look->link;
+ tempsv = BLI_ghash_lookup(vertgh,ev);
+
+ if(tempsv->down->v1 == ev){
+ tempev = tempsv->down->v2;
+ } else {
+ tempev = tempsv->down->v1;
+ }
+
+ ev->co[0] = ((tempsv->origvert.co[0]-tempev->co[0])*(1-fabs(perc))) + tempev->co[0];
+ ev->co[1] = ((tempsv->origvert.co[1]-tempev->co[1])*(1-fabs(perc))) + tempev->co[1];
+ ev->co[2] = ((tempsv->origvert.co[2]-tempev->co[2])*(1-fabs(perc))) + tempev->co[2];
+
+ look = look->next;
+ }
+ } else {
+ //non-prop code
+ }
+ }
+
+ sprintf(str, "Percentage %f", perc);
+ headerprint(str);
+
+ force_draw(0);
+ DAG_object_flush_update(G.scene, G.obedit, OB_RECALC_DATA);
+ scrarea_queue_winredraw(curarea);
+ }
+
+ getmouseco_areawin(mval);
+ if(mvalo[0] == -1){
+ mvalo[0] = mval[0];
+ mvalo[1] = mval[1];
+ }
+
+ if(mval[0] > mvalo[0]){
+ if(perc < 0.99)
+ perc += 0.01;
+
+ } else if(mval[0] < mvalo[0]){
+ if(perc > -0.99)
+ perc -= 0.01;
+ }
+
+ mvalo[0] = mval[0];
+
+ if(!immediate){
+ while(qtest()) {
+ unsigned short val=0;
+ event= extern_qread(&val); // extern_qread stores important events for the mainloop to handle
+
+
+ /* val==0 on key-release event */
+ if(val && (event==ESCKEY || ( event==LEFTMOUSE || event==RETKEY ))){
+ draw = 0;
+ }
+ if(val && (event==RIGHTMOUSE || event==ESCKEY || (event==MIDDLEMOUSE) )){
+ perc = 0;
+ immediate = 1;
+ }
+ if(val && (event==UPARROWKEY)){
+ if(perc <= 1.0){
+ perc += 0.01;
+ }
+ }
+ if(val && (event==DOWNARROWKEY)){
+ if(perc >= -1.0){
+ perc -= 0.01;
+ }
+ }
+ }
+ } else {
+ draw = 0;
+ }
+ }
+
+ //BLI_ghash_free(edgesgh, freeGHash, NULL);
+ BLI_ghash_free(vertgh,NULL,MEM_freeN);
+ BLI_linklist_free(vertlist,NULL);
+ BLI_linklist_free(edgelist,NULL);
+}
+
+//---------------------------------------------- OLD SUBDIVIDE -----------------------------------------------------
+
+/* ******************** SUBDIVIDE ********************************** */
+
+
+static void merge_weights(EditVert * vt, EditVert *vs )
+{
+ MDeformWeight *newdw;
+ int i,j,done;
+ for (j=0; j<vs->totweight; j++){
+ done=0;
+ /* Is vertex memeber of group */
+ /* If so: Change its weight */
+ for (i=0; i<vt->totweight; i++){
+ if (vt->dw[i].def_nr == vs->dw[j].def_nr)
+ { /* taking the maximum makes it independant from order of occurance */
+ if (vt->dw[i].weight < vs->dw[j].weight) vt->dw[i].weight = vs->dw[j].weight;
+ done=1;
+ break;
+ }
+ }
+ /* If not: Add the group and set its weight */
+ if (!done){
+ newdw = MEM_callocN (sizeof(MDeformWeight)*(vt->totweight+1), "deformWeight");
+ if (vt->dw){
+ memcpy (newdw, vt->dw, sizeof(MDeformWeight)*vt->totweight);
+ MEM_freeN (vt->dw);
+ }
+ vt->dw=newdw;
+ vt->dw[vt->totweight].weight=vs->dw[j].weight;
+ vt->dw[vt->totweight].def_nr=vs->dw[j].def_nr;
+ vt->totweight++;
+ }
+ }
+}
+
+
+static void set_weights(EditVert * vt, EditVert *vs1,EditVert *vs2,EditVert *vs3,EditVert *vs4 )
+{
+/*
+vt is a new generated vertex with empty deform group information
+vs1..v4 are egde neighbours holding group information
+so let the information ooze into the new one
+*/
+ if (vs1) merge_weights(vt,vs1);
+ if (vs2) merge_weights(vt,vs2);
+ if (vs3) merge_weights(vt,vs3);
+ if (vs4) merge_weights(vt,vs4);
+}
+
+
+
+
+static unsigned int cpack_fact(unsigned int col1, unsigned int col2, float fact)
+{
+ char *cp1, *cp2, *cp;
+ unsigned int col=0;
+ float facti;
+
+ facti=1-fact; /*result is (1-fact) * col1 and fact * col2 */
+
+ cp1= (char *)&col1;
+ cp2= (char *)&col2;
+ cp= (char *)&col;
+
+ cp[0]= (char)(facti*cp1[0]+fact*cp2[0]);
+ cp[1]= (char)(facti*cp1[1]+fact*cp2[1]);
+ cp[2]= (char)(facti*cp1[2]+fact*cp2[2]);
+ cp[3]= (char)(facti*cp1[3]+fact*cp2[3]);
+
+ return col;
+}
+
+
+static void uv_half(float *uv, float *uv1, float *uv2)
+{
+ uv[0]= (uv1[0]+uv2[0])/2.0f;
+ uv[1]= (uv1[1]+uv2[1])/2.0f;
+
+}
+
+static void uv_fact(float *uv, float *uv1, float *uv2, float fact)
+{
+ float facti = 1.0f - fact;
+ uv[0] = facti * uv1[0] + fact * uv2[0];
+ uv[1] = facti * uv1[1] + fact * uv2[1];
+}
+
+static void uv_quart(float *uv, float *uv1)
+{
+ uv[0]= (uv1[0]+uv1[2]+uv1[4]+uv1[6])/4.0f;
+ uv[1]= (uv1[1]+uv1[3]+uv1[5]+uv1[7])/4.0f;
+}
+
+static void face_pin_vertex(EditFace *efa, EditVert *vertex)
+{
+ if(efa->v1 == vertex) efa->tf.unwrap |= TF_PIN1;
+ else if(efa->v2 == vertex) efa->tf.unwrap |= TF_PIN2;
+ else if(efa->v3 == vertex) efa->tf.unwrap |= TF_PIN3;
+ else if(efa->v4 && vertex && efa->v4 == vertex) efa->tf.unwrap |= TF_PIN4;
+}
+
+static int vert_offset(EditFace *efa, EditVert *eve)
+{
+ if (efa->v1 == eve)
+ return 0;
+ if (efa->v2 == eve)
+ return 1;
+ if (efa->v3 == eve)
+ return 2;
+ if (efa->v4)
+ if (efa->v4 == eve)
+ return 3;
+ return -1;
+}
+
+static void set_wuv(int tot, EditFace *efa, int v1, int v2, int v3, int v4, EditFace *efapin)
+{
+ /* this weird function only to be used for subdivide, the 'w' in the name has no meaning! */
+ float *uv, uvo[4][2];
+ unsigned int *col, colo[4], col1, col2;
+ int a, v;
+
+ /* recover pinning */
+ if(efapin){
+ efa->tf.unwrap= 0;
+ if(efapin->tf.unwrap & TF_PIN1) face_pin_vertex(efa, efapin->v1);
+ if(efapin->tf.unwrap & TF_PIN2) face_pin_vertex(efa, efapin->v2);
+ if(efapin->tf.unwrap & TF_PIN3) face_pin_vertex(efa, efapin->v3);
+ if(efapin->tf.unwrap & TF_PIN4) face_pin_vertex(efa, efapin->v4);
+ }
+
+ memcpy(uvo, efa->tf.uv, sizeof(uvo));
+ uv= efa->tf.uv[0];
+ memcpy(colo, efa->tf.col, sizeof(colo));
+ col= efa->tf.col;
+
+ /*
+ Quads and Triangles reuse the same cases numbers, so we migh as well do both in the
+ same loop. Especially now that the offsets are calculated and not hardcoded, it's
+ much easier to reduce the code size (and make it less buggy).
+ */
+
+ /* ******************************************** */
+ /* */
+ /* Numbers corespond to verts (corner points), */
+ /* edge->vn's (center edges), the Center */
+ /* And the quincunx points of a face */
+ /* */
+ /* ******************************************** */
+
+ /* ******************************************** */
+ /* as shown here for quads: */
+ /* */
+ /* 2 ------- 5 -------- 1 */
+ /* | \ / | \ / | */
+ /* | 10 | 13 | */
+ /* | / \ | / \ | */
+ /* 6 ------- 9 -------- 8 */
+ /* | \ / | \ / | */
+ /* | 11 | 12 | */
+ /* | / \ | / \ | */
+ /* 3 ------- 7 -------- 4 */
+ /* */
+ /* ******************************************** */
+
+ /* ******************************************** */
+ /* and for triangles: */
+ /* 1 */
+ /* / \ */
+ /* / \ */
+ /* 5 7 */
+ /* / \ */
+ /* / \ */
+ /* 2 --------- 6 -------- 3 */
+ /* */
+ /* ******************************************** */
+
+ /* ******************************************** */
+ /* */
+ /* My talents in ascii arts are minimal so the */
+ /* drawings don't show all possible subdivision */
+ /* just draw them on paper if you need to. */
+ /* */
+ /* ******************************************** */
+
+ for(a=0; a<tot; a++, uv+=2, col++) {
+ /* edges that are subdivided, if any */
+ EditEdge *e1 = NULL, *e2 = NULL;
+ if(a==0) v= v1;
+ else if(a==1) v= v2;
+ else if(a==2) v= v3;
+ else v= v4;
+
+ if(a==3 && v4==0) break;
+
+ switch (v) {
+ /* Face corners, direct copy of the UVs and VCol */
+ case 1:
+ case 2:
+ case 3:
+ case 4:
+ uv[0]= uvo[v-1][0];
+ uv[1]= uvo[v-1][1];
+ *col= colo[v-1];
+ break;
+ /* Face sides (cutting an edge) */
+ /*
+ set the edge pointer accordingly, it's used latter to do the
+ actual calculations of the new UV and VCol
+ */
+ case 5:
+ e1 = efapin->e1;
+ break;
+ case 6:
+ e1 = efapin->e2;
+ break;
+ case 7:
+ e1 = efapin->e3;
+ break;
+ case 8:
+ e1 = efapin->e4;
+ break;
+
+ /* The following applies to Quads only */
+
+ /* Quad middle, just used when subdividing a quad as a whole */
+ /* (not knife nor loop cut) */
+ /* UVs and VCol is just the average of the four corners */
+ case 9:
+ uv_quart(uv, uvo[0]);
+ col1= cpack_fact(colo[1], colo[0], 0.5f);
+ col2= cpack_fact(colo[2], colo[3], 0.5f);
+ *col= cpack_fact(col1, col2, 0.5f);
+ break;
+ /* Quad corner cuts */
+ /* only when two adjacent edges are subdivided (and no others) */
+ /* Set both edge pointers accordingly, used later for calculations */
+ case 10: // case test==3 in subdivideflag()
+ e1 = efapin->e1;
+ e2 = efapin->e2;
+ break;
+ case 11: // case of test==6
+ e1 = efapin->e2;
+ e2 = efapin->e3;
+ break;
+ case 12: // case of test==12
+ e1 = efapin->e3;
+ e2 = efapin->e4;
+ break;
+ case 13: // case of test==9
+ e1 = efapin->e4;
+ e2 = efapin->e1;
+ break;
+ }
+ /* if splitting at least an edge */
+ if (e1) {
+ float percent;
+ int off1, off2;
+ /* if splitting two edges */
+ if (e2) {
+ float uv1[2], uv2[2];
+ /*
+ UV and VCol is obtained by using the middle ground of the weighted
+ average for both edges (weighted with Percent cut flag).
+ In a nutshell, the average of the cuts on both edges.
+ */
+ /* first cut */
+ off1 = vert_offset(efapin, e1->v1);
+ off2 = vert_offset(efapin, e1->v2);
+ percent = e1->f1 / 32768.0f;
+ uv_fact(uv1, uvo[off1], uvo[off2], percent);
+ col1= cpack_fact(colo[off1], colo[off2], percent);
+
+ /* second cut */
+ off1 = vert_offset(efapin, e2->v1);
+ off2 = vert_offset(efapin, e2->v2);
+ percent = e2->f1 / 32768.0f;
+ uv_fact(uv2, uvo[off1], uvo[off2], percent);
+ col2= cpack_fact(colo[off1], colo[off1], percent);
+
+ /* average the two */
+ uv_half(uv, uv1, uv2);
+ *col= cpack_fact(col1, col2, 0.5f);
+ }
+ /* or only one */
+ else {
+ /*
+ UV and VCol is obtained by using the weighted average
+ of both vertice (weighted with Percent cut flag).
+ */
+ off1 = vert_offset(efapin, e1->v1);
+ off2 = vert_offset(efapin, e1->v2);
+ percent = e1->f1 / 32768.0f;
+ uv_fact(uv, uvo[off1], uvo[off2], percent);
+ *col= cpack_fact(colo[off1], colo[off2], percent);
+ }
+ }
+ }
+}
+
+static EditVert *vert_from_number(EditFace *efa, int nr)
+{
+ switch(nr) {
+ case 0:
+ return 0;
+ case 1:
+ return efa->v1;
+ case 2:
+ return efa->v2;
+ case 3:
+ return efa->v3;
+ case 4:
+ return efa->v4;
+ case 5:
+ return efa->e1->vn;
+ case 6:
+ return efa->e2->vn;
+ case 7:
+ return efa->e3->vn;
+ case 8:
+ return efa->e4->vn;
+ }
+
+ return NULL;
+}
+
+static void addface_subdiv(EditFace *efa, int val1, int val2, int val3, int val4, EditVert *eve, EditFace *efapin)
+{
+ EditFace *w;
+ EditVert *v1, *v2, *v3, *v4;
+
+ if(val1>=9) v1= eve;
+ else v1= vert_from_number(efa, val1);
+
+ if(val2>=9) v2= eve;
+ else v2= vert_from_number(efa, val2);
+
+ if(val3>=9) v3= eve;
+ else v3= vert_from_number(efa, val3);
+
+ if(val4>=9) v4= eve;
+ else v4= vert_from_number(efa, val4);
+
+ w= addfacelist(v1, v2, v3, v4, efa, NULL);
+ if(w) {
+ if(efa->v4) set_wuv(4, w, val1, val2, val3, val4, efapin);
+ else set_wuv(3, w, val1, val2, val3, val4, efapin);
+ }
+}
+
+static float smoothperc= 0.0;
+
+static void smooth_subdiv_vec(float *v1, float *v2, float *n1, float *n2, float *vec)
+{
+ float len, fac, nor[3], nor1[3], nor2[3];
+
+ VecSubf(nor, v1, v2);
+ len= 0.5f*Normalise(nor);
+
+ VECCOPY(nor1, n1);
+ VECCOPY(nor2, n2);
+
+ /* cosine angle */
+ fac= nor[0]*nor1[0] + nor[1]*nor1[1] + nor[2]*nor1[2] ;
+
+ vec[0]= fac*nor1[0];
+ vec[1]= fac*nor1[1];
+ vec[2]= fac*nor1[2];
+
+ /* cosine angle */
+ fac= -nor[0]*nor2[0] - nor[1]*nor2[1] - nor[2]*nor2[2] ;
+
+ vec[0]+= fac*nor2[0];
+ vec[1]+= fac*nor2[1];
+ vec[2]+= fac*nor2[2];
+
+ vec[0]*= smoothperc*len;
+ vec[1]*= smoothperc*len;
+ vec[2]*= smoothperc*len;
+}
+
+static void smooth_subdiv_quad(EditFace *efa, float *vec)
+{
+
+ float nor1[3], nor2[3];
+ float vec1[3], vec2[3];
+ float cent[3];
+
+ /* vlr->e1->vn is new vertex inbetween v1 / v2 */
+
+ VecMidf(nor1, efa->v1->no, efa->v2->no);
+ Normalise(nor1);
+ VecMidf(nor2, efa->v3->no, efa->v4->no);
+ Normalise(nor2);
+
+ smooth_subdiv_vec( efa->e1->vn->co, efa->e3->vn->co, nor1, nor2, vec1);
+
+ VecMidf(nor1, efa->v2->no, efa->v3->no);
+ Normalise(nor1);
+ VecMidf(nor2, efa->v4->no, efa->v1->no);
+ Normalise(nor2);
+
+ smooth_subdiv_vec( efa->e2->vn->co, efa->e4->vn->co, nor1, nor2, vec2);
+
+ VecAddf(vec1, vec1, vec2);
+
+ CalcCent4f(cent, efa->v1->co, efa->v2->co, efa->v3->co, efa->v4->co);
+ VecAddf(vec, cent, vec1);
+}
+
+void subdivideflag(int flag, float rad, int beauty)
+{
+ EditMesh *em = G.editMesh;
+ /* subdivide all with (vertflag & flag) */
+ /* if rad>0.0 it's a 'sphere' subdivide */
+ /* if rad<0.0 it's a fractal subdivide */
+ extern float doublimit;
+ EditVert *eve;
+ EditEdge *eed, *e1, *e2, *e3, *e4, *nexted;
+ EditFace *efa, efapin;
+ float fac, vec[3], vec1[3], len1, len2, len3, percent;
+ short test;
+
+ printf("in old subdivideflag\n");
+
+ if(beauty & B_SMOOTH) {
+ short perc= 100;
+
+ if(button(&perc, 10, 500, "Percentage:")==0) return;
+
+ smoothperc= 0.292f*perc/100.0f;
+ }
+
+ /* edgeflags */
+ if((beauty & B_KNIFE)==0) { // knife option sets own flags
+ eed= em->edges.first;
+ while(eed) {
+ if( (eed->v1->f & flag) && (eed->v2->f & flag) ) eed->f2= flag;
+ else eed->f2= 0;
+ eed= eed->next;
+ }
+ }
+
+ /* if beauty: test for area and clear edge flags of 'ugly' edges */
+ if(beauty & B_BEAUTY) {
+ efa= em->faces.first;
+ while(efa) {
+ if( faceselectedAND(efa, flag) ) {
+ if(efa->v4) {
+
+ /* area */
+ len1= AreaQ3Dfl(efa->v1->co, efa->v2->co, efa->v3->co, efa->v4->co);
+ if(len1 <= doublimit) {
+ efa->e1->f2 = 0;
+ efa->e2->f2 = 0;
+ efa->e3->f2 = 0;
+ efa->e4->f2 = 0;
+ }
+ else {
+ len1= VecLenf(efa->v1->co, efa->v2->co) + VecLenf(efa->v3->co, efa->v4->co);
+ len2= VecLenf(efa->v2->co, efa->v3->co) + VecLenf(efa->v1->co, efa->v4->co);
+
+ if(len1 < len2) {
+ efa->e1->f2 = 0;
+ efa->e3->f2 = 0;
+ }
+ else if(len1 > len2) {
+ efa->e2->f2 = 0;
+ efa->e4->f2 = 0;
+ }
+ }
+ }
+ else {
+ /* area */
+ len1= AreaT3Dfl(efa->v1->co, efa->v2->co, efa->v3->co);
+ if(len1 <= doublimit) {
+ efa->e1->f2 = 0;
+ efa->e2->f2 = 0;
+ efa->e3->f2 = 0;
+ }
+ else {
+ len1= VecLenf(efa->v1->co, efa->v2->co) ;
+ len2= VecLenf(efa->v2->co, efa->v3->co) ;
+ len3= VecLenf(efa->v3->co, efa->v1->co) ;
+
+ if(len1<len2 && len1<len3) {
+ efa->e1->f2 = 0;
+ }
+ else if(len2<len3 && len2<len1) {
+ efa->e2->f2 = 0;
+ }
+ else if(len3<len2 && len3<len1) {
+ efa->e3->f2 = 0;
+ }
+ }
+ }
+ }
+ efa= efa->next;
+ }
+ }
+
+ if(beauty & B_SMOOTH) {
+
+ vertexnormals(0); /* no1*/
+
+ }
+
+ /* make new normal and put in edge, clear flag! needed for face creation part below */
+ eed= em->edges.first;
+ while(eed) {
+ if(eed->f2 & flag) {
+ /* for now */
+ eed->h &= ~EM_FGON;
+
+ /* Subdivide percentage is stored in 1/32768ths in eed->f1 */
+ if (beauty & B_PERCENTSUBD) percent=(float)(eed->f1)/32768.0f;
+ else {
+ eed->f1 = 32768 / 2;
+ percent=0.5f;
+ }
+
+ vec[0]= (1-percent)*eed->v1->co[0] + percent*eed->v2->co[0];
+ vec[1]= (1-percent)*eed->v1->co[1] + percent*eed->v2->co[1];
+ vec[2]= (1-percent)*eed->v1->co[2] + percent*eed->v2->co[2];
+
+ if(rad > 0.0) { /* subdivide sphere */
+ Normalise(vec);
+ vec[0]*= rad;
+ vec[1]*= rad;
+ vec[2]*= rad;
+ }
+ else if(rad< 0.0) { /* fractal subdivide */
+ fac= rad* VecLenf(eed->v1->co, eed->v2->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());
+ VecAddf(vec, vec, vec1);
+ }
+
+ if(beauty & B_SMOOTH) {
+ smooth_subdiv_vec(eed->v1->co, eed->v2->co, eed->v1->no, eed->v2->no, vec1);
+ VecAddf(vec, vec, vec1);
+ }
+
+ eed->vn= addvertlist(vec);
+ eed->vn->f= eed->v1->f;
+
+ }
+ else eed->vn= 0;
+
+ eed->f2= 0; /* needed! */
+
+ eed= eed->next;
+ }
+
+ /* test all faces for subdivide edges, there are 8 or 16 cases (ugh)! */
+
+ efa= em->faces.last;
+ while(efa) {
+
+ efapin= *efa; /* make a copy of efa to recover uv pinning later */
+
+ if( faceselectedOR(efa, flag) ) {
+ /* for now */
+ efa->fgonf= 0;
+
+ e1= efa->e1;
+ e2= efa->e2;
+ e3= efa->e3;
+ e4= efa->e4;
+
+ test= 0;
+ if(e1 && e1->vn) {
+ test+= 1;
+ e1->f2= 1;
+ /* add edges here, to copy correct edge data */
+ eed= addedgelist(e1->v1, e1->vn, e1);
+ eed= addedgelist(e1->vn, e1->v2, e1);
+ set_weights(e1->vn, e1->v1,e1->v2,NULL,NULL);
+ }
+ if(e2 && e2->vn) {
+ test+= 2;
+ e2->f2= 1;
+ /* add edges here, to copy correct edge data */
+ eed= addedgelist(e2->v1, e2->vn, e2);
+ eed= addedgelist(e2->vn, e2->v2, e2);
+ set_weights(e2->vn, e2->v1,e2->v2,NULL,NULL);
+ }
+ if(e3 && e3->vn) {
+ test+= 4;
+ e3->f2= 1;
+ /* add edges here, to copy correct edge data */
+ eed= addedgelist(e3->v1, e3->vn, e3);
+ eed= addedgelist(e3->vn, e3->v2, e3);
+ set_weights(e3->vn, e3->v1,e3->v2,NULL,NULL);
+ }
+ if(e4 && e4->vn) {
+ test+= 8;
+ e4->f2= 1;
+ /* add edges here, to copy correct edge data */
+ eed= addedgelist(e4->v1, e4->vn, e4);
+ eed= addedgelist(e4->vn, e4->v2, e4);
+ set_weights(e4->vn, e4->v1,e4->v2,NULL,NULL);
+ }
+ if(test) {
+ if(efa->v4==0) { /* All the permutations of 3 edges*/
+ if((test & 3)==3) addface_subdiv(efa, 2, 2+4, 1+4, 0, 0, &efapin);
+ if((test & 6)==6) addface_subdiv(efa, 3, 3+4, 2+4, 0, 0, &efapin);
+ if((test & 5)==5) addface_subdiv(efa, 1, 1+4, 3+4, 0, 0, &efapin);
+
+ if(test==7) { /* four new faces, old face renews */
+ efa->v1= e1->vn;
+ efa->v2= e2->vn;
+ efa->v3= e3->vn;
+ set_wuv(3, efa, 1+4, 2+4, 3+4, 0, &efapin);
+ }
+ else if(test==3) {
+ addface_subdiv(efa, 1+4, 2+4, 3, 0, 0, &efapin);
+ efa->v2= e1->vn;
+ set_wuv(3, efa, 1, 1+4, 3, 0, &efapin);
+ }
+ else if(test==6) {
+ addface_subdiv(efa, 2+4, 3+4, 1, 0, 0, &efapin);
+ efa->v3= e2->vn;
+ set_wuv(3, efa, 1, 2, 2+4, 0, &efapin);
+ }
+ else if(test==5) {
+ addface_subdiv(efa, 3+4, 1+4, 2, 0, 0, &efapin);
+ efa->v1= e3->vn;
+ set_wuv(3, efa, 3+4, 2, 3, 0, &efapin);
+ }
+ else if(test==1) {
+ addface_subdiv(efa, 1+4, 2, 3, 0, 0, &efapin);
+ efa->v2= e1->vn;
+ set_wuv(3, efa, 1, 1+4, 3, 0, &efapin);
+ }
+ else if(test==2) {
+ addface_subdiv(efa, 2+4, 3, 1, 0, 0, &efapin);
+ efa->v3= e2->vn;
+ set_wuv(3, efa, 1, 2, 2+4, 0, &efapin);
+ }
+ else if(test==4) {
+ addface_subdiv(efa, 3+4, 1, 2, 0, 0, &efapin);
+ efa->v1= e3->vn;
+ set_wuv(3, efa, 3+4, 2, 3, 0, &efapin);
+ }
+ efa->e1= addedgelist(efa->v1, efa->v2, NULL);
+ efa->e2= addedgelist(efa->v2, efa->v3, NULL);
+ efa->e3= addedgelist(efa->v3, efa->v1, NULL);
+
+ }
+ else { /* All the permutations of 4 faces */
+ if(test==15) {
+ /* add a new point in center */
+ CalcCent4f(vec, efa->v1->co, efa->v2->co, efa->v3->co, efa->v4->co);
+
+ if(beauty & B_SMOOTH) {
+ smooth_subdiv_quad(efa, vec); /* adds */
+ }
+ eve= addvertlist(vec);
+ set_weights(eve, efa->v1,efa->v2,efa->v3,efa->v4);
+ eve->f |= flag;
+
+ addface_subdiv(efa, 2, 2+4, 9, 1+4, eve, &efapin);
+ addface_subdiv(efa, 3, 3+4, 9, 2+4, eve, &efapin);
+ addface_subdiv(efa, 4, 4+4, 9, 3+4, eve, &efapin);
+
+ efa->v2= e1->vn;
+ efa->v3= eve;
+ efa->v4= e4->vn;
+ set_wuv(4, efa, 1, 1+4, 9, 4+4, &efapin);
+ }
+ else {
+ if(((test & 3)==3)&&(test!=3)) addface_subdiv(efa, 1+4, 2, 2+4, 0, 0, &efapin);
+ if(((test & 6)==6)&&(test!=6)) addface_subdiv(efa, 2+4, 3, 3+4, 0, 0, &efapin);
+ if(((test & 12)==12)&&(test!=12)) addface_subdiv(efa, 3+4, 4, 4+4, 0, 0, &efapin);
+ if(((test & 9)==9)&&(test!=9)) addface_subdiv(efa, 4+4, 1, 1+4, 0, 0, &efapin);
+
+ if(test==1) { /* Edge 1 has new vert */
+ addface_subdiv(efa, 1+4, 2, 3, 0, 0, &efapin);
+ addface_subdiv(efa, 1+4, 3, 4, 0, 0, &efapin);
+ efa->v2= e1->vn;
+ efa->v3= efa->v4;
+ efa->v4= 0;
+ set_wuv(4, efa, 1, 1+4, 4, 0, &efapin);
+ }
+ else if(test==2) { /* Edge 2 has new vert */
+ addface_subdiv(efa, 2+4, 3, 4, 0, 0, &efapin);
+ addface_subdiv(efa, 2+4, 4, 1, 0, 0, &efapin);
+ efa->v3= e2->vn;
+ efa->v4= 0;
+ set_wuv(4, efa, 1, 2, 2+4, 0, &efapin);
+ }
+ else if(test==4) { /* Edge 3 has new vert */
+ addface_subdiv(efa, 3+4, 4, 1, 0, 0, &efapin);
+ addface_subdiv(efa, 3+4, 1, 2, 0, 0, &efapin);
+ efa->v1= efa->v2;
+ efa->v2= efa->v3;
+ efa->v3= e3->vn;
+ efa->v4= 0;
+ set_wuv(4, efa, 2, 3, 3+4, 0, &efapin);
+ }
+ else if(test==8) { /* Edge 4 has new vert */
+ addface_subdiv(efa, 4+4, 1, 2, 0, 0, &efapin);
+ addface_subdiv(efa, 4+4, 2, 3, 0, 0, &efapin);
+ efa->v1= efa->v3;
+ efa->v2= efa->v4;
+ efa->v3= e4->vn;
+ efa->v4= 0;
+ set_wuv(4, efa, 3, 4, 4+4, 0, &efapin);
+ }
+ else if(test==3) { /*edge 1&2 */
+ /* make new vert in center of new edge */
+ vec[0]=(e1->vn->co[0]+e2->vn->co[0])/2;
+ vec[1]=(e1->vn->co[1]+e2->vn->co[1])/2;
+ vec[2]=(e1->vn->co[2]+e2->vn->co[2])/2;
+ eve= addvertlist(vec);
+ set_weights(eve, e1->vn,e2->vn,NULL,NULL);
+ eve->f |= flag;
+ /* Add new faces */
+ addface_subdiv(efa, 4, 10, 2+4, 3, eve, &efapin);
+ addface_subdiv(efa, 4, 1, 1+4, 10, eve, &efapin);
+ /* orig face becomes small corner */
+ efa->v1=e1->vn;
+ //efa->v2=efa->v2;
+ efa->v3=e2->vn;
+ efa->v4=eve;
+
+ set_wuv(4, efa, 1+4, 2, 2+4, 10, &efapin);
+ }
+ else if(test==6) { /* 2&3 */
+ /* make new vert in center of new edge */
+ vec[0]=(e2->vn->co[0]+e3->vn->co[0])/2;
+ vec[1]=(e2->vn->co[1]+e3->vn->co[1])/2;
+ vec[2]=(e2->vn->co[2]+e3->vn->co[2])/2;
+ eve= addvertlist(vec);
+ set_weights(eve, e2->vn,e3->vn,NULL,NULL);
+ eve->f |= flag;
+ /*New faces*/
+ addface_subdiv(efa, 1, 11, 3+4, 4, eve, &efapin);
+ addface_subdiv(efa, 1, 2, 2+4, 11, eve, &efapin);
+ /* orig face becomes small corner */
+ efa->v1=e2->vn;
+ efa->v2=efa->v3;
+ efa->v3=e3->vn;
+ efa->v4=eve;
+
+ set_wuv(4, efa, 2+4, 3, 3+4, 11, &efapin);
+ }
+ else if(test==12) { /* 3&4 */
+ /* make new vert in center of new edge */
+ vec[0]=(e3->vn->co[0]+e4->vn->co[0])/2;
+ vec[1]=(e3->vn->co[1]+e4->vn->co[1])/2;
+ vec[2]=(e3->vn->co[2]+e4->vn->co[2])/2;
+ eve= addvertlist(vec);
+ set_weights(eve, e3->vn,e4->vn,NULL,NULL);
+ eve->f |= flag;
+ /*New Faces*/
+ addface_subdiv(efa, 2, 12, 4+4, 1, eve, &efapin);
+ addface_subdiv(efa, 2, 3, 3+4, 12, eve, &efapin);
+ /* orig face becomes small corner */
+ efa->v1=e3->vn;
+ efa->v2=efa->v4;
+ efa->v3=e4->vn;
+ efa->v4=eve;
+
+ set_wuv(4, efa, 3+4, 4, 4+4, 12, &efapin);
+ }
+ else if(test==9) { /* 4&1 */
+ /* make new vert in center of new edge */
+ vec[0]=(e1->vn->co[0]+e4->vn->co[0])/2;
+ vec[1]=(e1->vn->co[1]+e4->vn->co[1])/2;
+ vec[2]=(e1->vn->co[2]+e4->vn->co[2])/2;
+ eve= addvertlist(vec);
+ set_weights(eve, e1->vn,e4->vn,NULL,NULL);
+ eve->f |= flag;
+ /*New Faces*/
+ addface_subdiv(efa, 3, 13, 1+4, 2, eve, &efapin);
+ addface_subdiv(efa, 3, 4, 4+4,13, eve, &efapin);
+ /* orig face becomes small corner */
+ efa->v2=efa->v1;
+ efa->v1=e4->vn;
+ efa->v3=e1->vn;
+ efa->v4=eve;
+
+ set_wuv(4, efa, 4+4, 1, 1+4, 13, &efapin);
+ }
+ else if(test==5) { /* 1&3 */
+ addface_subdiv(efa, 1+4, 2, 3, 3+4, 0, &efapin);
+ efa->v2= e1->vn;
+ efa->v3= e3->vn;
+ set_wuv(4, efa, 1, 1+4, 3+4, 4, &efapin);
+ }
+ else if(test==10) { /* 2&4 */
+ addface_subdiv(efa, 2+4, 3, 4, 4+4, 0, &efapin);
+ efa->v3= e2->vn;
+ efa->v4= e4->vn;
+ set_wuv(4, efa, 1, 2, 2+4, 4+4, &efapin);
+ }/* Unfortunately, there is no way to avoid tris on 1 or 3 edges*/
+ else if(test==7) { /*1,2&3 */
+ addface_subdiv(efa, 1+4, 2+4, 3+4, 0, 0, &efapin);
+ efa->v2= e1->vn;
+ efa->v3= e3->vn;
+ set_wuv(4, efa, 1, 1+4, 3+4, 4, &efapin);
+ }
+
+ else if(test==14) { /* 2,3&4 */
+ addface_subdiv(efa, 2+4, 3+4, 4+4, 0, 0, &efapin);
+ efa->v3= e2->vn;
+ efa->v4= e4->vn;
+ set_wuv(4, efa, 1, 2, 2+4, 4+4, &efapin);
+ }
+ else if(test==13) {/* 1,3&4 */
+ addface_subdiv(efa, 3+4, 4+4, 1+4, 0, 0, &efapin);
+ efa->v4= e3->vn;
+ efa->v1= e1->vn;
+ set_wuv(4, efa, 1+4, 2, 3, 3+4, &efapin);
+ }
+ else if(test==11) { /* 1,2,&4 */
+ addface_subdiv(efa, 4+4, 1+4, 2+4, 0, 0, &efapin);
+ efa->v1= e4->vn;
+ efa->v2= e2->vn;
+ set_wuv(4, efa, 4+4, 2+4, 3, 4, &efapin);
+ }
+ }
+ efa->e1= addedgelist(efa->v1, efa->v2, NULL);
+ efa->e2= addedgelist(efa->v2, efa->v3, NULL);
+ if(efa->v4) efa->e3= addedgelist(efa->v3, efa->v4, NULL);
+ else efa->e3= addedgelist(efa->v3, efa->v1, NULL);
+ if(efa->v4) efa->e4= addedgelist(efa->v4, efa->v1, NULL);
+ else efa->e4= NULL;
+ }
+ }
+ }
+ efa= efa->prev;
+ }
+
+ /* remove all old edges, if needed make new ones */
+ eed= em->edges.first;
+ while(eed) {
+ nexted= eed->next;
+ if( eed->vn ) {
+ eed->vn->f |= 16;
+ if(eed->f2==0) { /* not used in face */
+ addedgelist(eed->v1, eed->vn, eed);
+ addedgelist(eed->vn, eed->v2, eed);
+ }
+ remedge(eed);
+ free_editedge(eed);
+ }
+ eed= nexted;
+ }
+
+ /* since this is all on vertex level, flush vertex selection */
+ EM_select_flush();
+ recalc_editnormals();
+
+ countall();
+ allqueue(REDRAWVIEW3D, 0);
+ DAG_object_flush_update(G.scene, G.obedit, OB_RECALC_DATA);
+}
diff --git a/source/blender/src/editobject.c b/source/blender/src/editobject.c
index 8098f01970d..f01b88a2a78 100644
--- a/source/blender/src/editobject.c
+++ b/source/blender/src/editobject.c
@@ -1897,7 +1897,7 @@ void special_editmenu(void)
extern float doublimit;
float fac;
int nr,ret;
- short randfac;
+ short randfac,numcuts;
if(G.obpose) {
pose_special_editmenu();
@@ -2024,26 +2024,38 @@ void special_editmenu(void)
}
}
else if(G.obedit->type==OB_MESH) {
-
- nr= pupmenu("Specials%t|Subdivide%x1|Subdivide Fractal%x2|Subdivide Smooth%x3|Merge%x4|Remove Doubles%x5|Hide%x6|Reveal%x7|Select Swap%x8|Flip Normals %x9|Smooth %x10|Bevel %x11");
- if(nr>0) waitcursor(1);
+
+ nr= pupmenu("Specials%t|Subdivide%x1|Subdivide Multi%x2|Subdivide Multi Fractal%x3|Subdivide Multi Smooth - WIP%x12|Subdivide Smooth Old%x13|Merge%x4|Remove Doubles%x5|Hide%x6|Reveal%x7|Select Swap%x8|Flip Normals %x9|Smooth %x10|Bevel %x11");
+ //if(nr>0) waitcursor(1);
switch(nr) {
case 1:
- subdivideflag(1, 0.0, editbutflag);
- BIF_undo_push("Subdivide");
+ numcuts = 1;
+ waitcursor(1);
+ esubdivideflag(1, 0.0, editbutflag,numcuts,0);
+
+ BIF_undo_push("ESubdivide Single");
+ //subdivideflag(1, 0.0, editbutflag);
+ //BIF_undo_push("Subdivide");
break;
case 2:
+ numcuts = 2;
+ if(button(&numcuts, 1, 128, "Number of Cuts:")==0) return;
+ waitcursor(1);
+ esubdivideflag(1, 0.0, editbutflag,numcuts,0);
+ BIF_undo_push("ESubdivide");
+ break;
+ case 3:
+ numcuts = 2;
+ if(button(&numcuts, 1, 128, "Number of Cuts:")==0) return;
+ waitcursor(1);
randfac= 10;
if(button(&randfac, 1, 100, "Rand fac:")==0) return;
fac= -( (float)randfac )/100;
- subdivideflag(1, fac, editbutflag);
+ esubdivideflag(1, fac, editbutflag,numcuts,0);
BIF_undo_push("Subdivide Fractal");
break;
- case 3:
- subdivideflag(1, 0.0, editbutflag | B_SMOOTH);
- BIF_undo_push("Subdivide Smooth");
- break;
+
case 4:
mergemenu();
break;
@@ -2070,7 +2082,19 @@ void special_editmenu(void)
case 11:
bevel_menu();
break;
- }
+ case 12:
+ numcuts = 2;
+ if(button(&numcuts, 1, 128, "Number of Cuts:")==0) return;
+ waitcursor(1);
+ esubdivideflag(1, 0.0, editbutflag | B_SMOOTH,numcuts,0);
+ BIF_undo_push("Subdivide Smooth");
+ break;
+ case 13:
+ waitcursor(1);
+ subdivideflag(1, 0.0, editbutflag | B_SMOOTH);
+ BIF_undo_push("Subdivide Smooth");
+ break;
+ }
DAG_object_flush_update(G.scene, G.obedit, OB_RECALC_DATA);
diff --git a/source/blender/src/header_view3d.c b/source/blender/src/header_view3d.c
index 340ee0b88b4..c35d1f71177 100644
--- a/source/blender/src/header_view3d.c
+++ b/source/blender/src/header_view3d.c
@@ -819,9 +819,6 @@ void do_view3d_select_meshmenu(void *arg, int event)
case 5: /* select random */
selectrandom_mesh();
break;
- case 6: /* select Faceloop */
- loopoperations(LOOP_SELECT);
- break;
case 7: /* select more */
select_more();
break;
@@ -831,9 +828,6 @@ void do_view3d_select_meshmenu(void *arg, int event)
case 9: /* select less */
select_non_manifold();
break;
- case 10: /* select vertexloop */
- vertex_loop_select();
- break;
}
allqueue(REDRAWVIEW3D, 0);
}
@@ -873,8 +867,6 @@ static uiBlock *view3d_select_meshmenu(void *arg_unused)
uiDefBut(block, SEPR, 0, "", 0, yco-=6,
menuwidth, 6, NULL, 0.0, 0.0, 0, 0, "");
- uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Face Loop...|Shift R", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 6, "");
- uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Vertex Loop|Alt B", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 10, "");
uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Linked Vertices|Ctrl L", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 4, "");
if(curarea->headertype==HEADERTOP) {
@@ -2088,25 +2080,25 @@ void do_view3d_edit_mesh_edgesmenu(void *arg, int event)
switch(event) {
case 0: /* subdivide smooth */
- subdivideflag(1, 0.0, editbutflag | B_SMOOTH);
+ esubdivideflag(1, 0.0, editbutflag | B_SMOOTH,1,0);
BIF_undo_push("Subdivide Smooth");
break;
case 1: /*subdivide fractal */
randfac= 10;
if(button(&randfac, 1, 100, "Rand fac:")==0) return;
fac= -( (float)randfac )/100;
- subdivideflag(1, fac, editbutflag);
+ esubdivideflag(1, fac, editbutflag,1,0);
BIF_undo_push("Subdivide Fractal");
break;
case 2: /* subdivide */
- subdivideflag(1, 0.0, editbutflag);
+ esubdivideflag(1, 0.0, editbutflag,1,0);
BIF_undo_push("Subdivide");
break;
case 3: /* knife subdivide */
KnifeSubdivide(KNIFE_PROMPT);
break;
case 4: /* Loop subdivide */
- loopoperations(LOOP_CUT);
+ CutEdgeloop(1);
break;
case 5: /* Make Edge/Face */
addedgeface_mesh();
@@ -2130,6 +2122,9 @@ void do_view3d_edit_mesh_edgesmenu(void *arg, int event)
case 11: /* Rotate Edge */
edge_rotate_selected(1);
break;
+ case 12: /* Edgeslide */
+ EdgeSlide(0,0.0);
+ break;
}
allqueue(REDRAWVIEW3D, 0);
}
@@ -2170,7 +2165,10 @@ static uiBlock *view3d_edit_mesh_edgesmenu(void *arg_unused)
uiDefBut(block, SEPR, 0, "", 0, yco-=6, menuwidth, 6, NULL, 0.0, 0.0, 0, 0, "");
uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Rotate Edge CW|Ctrl E", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 10, "");
- uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Rotate Edge CCW|Ctrl E", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 10, "");
+ uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Rotate Edge CCW|Ctrl E", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 11, "");
+
+ uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Edgeslide |Ctrl E", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 12, "");
+
uiBlockSetDirection(block, UI_RIGHT);
uiTextBoundsBlock(block, 60);
diff --git a/source/blender/src/space.c b/source/blender/src/space.c
index dee2d7c0e92..7300135c86f 100644
--- a/source/blender/src/space.c
+++ b/source/blender/src/space.c
@@ -1132,14 +1132,6 @@ static void winqreadview3dspace(ScrArea *sa, void *spacedata, BWinEvent *evt)
case BKEY:
if((G.qual==LR_SHIFTKEY))
set_render_border();
- else if((G.qual==LR_ALTKEY)){
- if(G.obedit && G.obedit->type==OB_MESH) {
- /* Loop Select Operations */
- /* Vertexloop */
- /* Faceloop */
- vertex_loop_select();
- }
- }
else if((G.qual==0))
borderselect();
break;
@@ -1535,12 +1527,11 @@ static void winqreadview3dspace(ScrArea *sa, void *spacedata, BWinEvent *evt)
if((G.qual==LR_SHIFTKEY)) {
if ELEM(G.obedit->type, OB_CURVE, OB_SURF)
selectrow_nurb();
- else if (G.obedit->type==OB_MESH)
- loopoperations(LOOP_SELECT);
}
else if(G.qual==LR_CTRLKEY) {
if (G.obedit->type==OB_MESH)
- loopoperations(LOOP_CUT);
+ CutEdgeloop(1);
+ BIF_undo_push("Cut Edgeloop");
}
else if((G.qual==0)) {
initTransform(TFM_ROTATION, CTX_NONE);
diff --git a/source/blender/src/toolbox.c b/source/blender/src/toolbox.c
index 5f9c66386db..9c46f2f5e16 100644
--- a/source/blender/src/toolbox.c
+++ b/source/blender/src/toolbox.c
@@ -1735,7 +1735,10 @@ static TBitem tb_mesh_edit_edge[]= {
{ 0, "SEPR", 0, NULL},
{ 0, "Crease SubSurf|Shift E", 9, NULL},
{ 0, "SEPR", 0, NULL},
-{ 0, "Rotate Edge|Ctrl E", 10, NULL},
+{ 0, "Rotate Edge CW|Ctrl E", 10, NULL},
+{ 0, "Rotate Edge CCW|Ctrl E", 11, NULL},
+{ 0, "SEPR", 0, NULL},
+{ 0, "Edgeslide|Ctrl E", 12, NULL},
{ -1, "", 0, do_view3d_edit_mesh_edgesmenu}};
static TBitem tb_mesh_edit_face[]= {