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:
-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[]= {