[Bf-committers] Edge Select and Cut Tool

desoto bf-committers@blender.org
Sat, 20 Dec 2003 10:53:46 -0500


This is a multi-part message in MIME format.
--------------030105060304040600060806
Content-Type: text/plain; charset=ISO-8859-1; format=flowed
Content-Transfer-Encoding: 7bit

Not sure how many of you remember but I was working on this a while back 
and I'm pretty sure I got it working completely.  There's probably bugs 
with it but if anyone wants to take a look at it for inclusion in 
Blender that'd be cool. Its not pretty and I'm sure it needs some work 
but until I've got a reason to keep working on it its just going to sit 
and rot on my comp.  Hope someone likes it.   Thanks.

Desoto
a.k.a. Chris

P.S.  This code belongs in EditMesh.c and a couple modifications had to 
be made to the K-Key menu to add it in.  Theres more to know about it 
but I'll wait for someone to ask before I start messing with it. 



--------------030105060304040600060806
Content-Type: text/plain;
 name="edge_select_cut.c"
Content-Transfer-Encoding: 7bit
Content-Disposition: inline;
 filename="edge_select_cut.c"

void EdgeSubdivide(char mode){
	int oldcursor, mousemove=1, midpointblocks=1, numpts=0, i=0, highlight=0;
	short isect=0, mval[2];
	EditEdge *eed, *lastedge, *firstedge;
	EditVlak *evl;
	float *midpoints, *temp, mval2[2], dist1, dist2, dist3, dist4, v1[2], v2[2], perc, percent;	

	midpoints=(float *)MEM_callocN(256*3*sizeof(float),"Edge Midpoints");
	
	undo_push_mesh("Edge Cut");
	
	oldcursor=get_cursor();
	set_cursor(CURSOR_PENCIL); 
	
	calc_meshverts_ext();  /*Update screen coords for current window */
	
	if (mode==EDGE_PROMPT) mode=pupmenu("Edge Cut Type %t|Edge Select (Exact)%x1|Edge Select (Midpoints)%x2|");
	
	while(mousemove) {
			
		headerprint("Select consecutive edges for subdivision.");
		
		scrarea_do_windraw(curarea);
			
		persp(PERSP_VIEW);
			
		eed= findnearestedge();
			
		glPushMatrix();
			
		mymultmatrix(G.obedit->obmat);			
			
		if(numpts > 2) { /* If more than one edge has been selected, draw the preview line between two or more edges in yellow */
			glColor3ub(255, 255, 0);
			glBegin(GL_LINE_STRIP);
			i=0;
			while (i<numpts) {
				glVertex3f(midpoints[i], midpoints[i+1], midpoints[i+2]);
				i+=3;
			}	
			glEnd();
		}
		
		if(numpts > 2) { /* If the first edge has already been selected, highlight it in orange on each pass through the loop */
			glBegin(GL_LINES);
			glColor3ub(255, 150, 0);
			glVertex3fv(firstedge->v1->co);
			glVertex3fv(firstedge->v2->co);
			glEnd();
		}
		
		glPopMatrix();				
		
		if(eed) {
			if (numpts!=0) {
				for(evl=G.edvl.first; evl!=0; evl=evl->next) {
					if (evl->e1 == eed) { /* Is this edge the same as the nearest edge? */
						if ((evl->e2 == lastedge) || (evl->e3 == lastedge) || ((evl->e4) && (evl->e4 == lastedge))) { /* Is this edge the same edge I just picked? */
							highlight=1; /* Ooh!  That means eed shares a face with the last edge I picked! Its ok to select it. */
						}
					}	
					else if (evl->e2 == eed) {
						if ((evl->e1 == lastedge) || (evl->e3 == lastedge) || ((evl->e4) && (evl->e4 == lastedge))) {
							highlight=1;
						}
					}
					else if ((evl->e3 == eed)) {
						if ((evl->e1 == lastedge) || (evl->e2 == lastedge) || ((evl->e4) && (evl->e4 == lastedge))) {
							highlight=1;
						}
					}
					else if ((evl->e4) && (evl->e4 == eed)) { /* There isn't always a fourth edge. */
						if ((evl->e1 == lastedge) || (evl->e2 == lastedge) || (evl->e3 == lastedge)) {
							highlight=1;
						}
					}
				}
			}
			else { /* If There is an edge found and no edges have been flagged yet.. */ 
				highlight=1; /* Permit it to be highlighted in yellow and to be selected */					
			}
			
			glPushMatrix();
		
			mymultmatrix(G.obedit->obmat);
		
			if(highlight==1) { /* If eed is permitted to be highlighted, do so by drawing a yellow line over it */
				glColor3ub(255, 255, 0);
				glBegin(GL_LINES);
				glVertex3fv(eed->v1->co);
				glVertex3fv(eed->v2->co);
				glEnd();
			}
		
			glPopMatrix();
			
			while(qtest()) {
				unsigned short val;
				short event= extern_qread(&val);
			
				if(val && (event==RETKEY)) {
					mousemove= 0;
				}
				else if (val && (event==LEFTMOUSE) && (highlight==1)) {
					if (numpts==0) { /* And the number of edges selected is zero */
						firstedge=eed; /* Mark the selected edge as the first edge */
					}
				
					if (mode==1) {
						getmouseco_areawin(mval);
					
						mval2[0]=(float)mval[0];
						mval2[1]=(float)mval[1];
						
						v1[0] = eed->v1->xs;  			/* oh great! the screencoordinates are not an array....grrrr*/
						v1[1] = eed->v1->ys;
						v2[0] = eed->v2->xs;
						v2[1] = eed->v2->ys;
					
						dist1 = PdistVL2Dfl(mval2,v1,v2);
						dist3 = sqrt(( (mval[0] - v1[0]) * (mval[0] - v1[0]) ) + ( (mval[1] - v1[1]) * (mval[1] - v1[1]) ));
						
						dist2 = sqrt((dist3 * dist3) - (dist1 * dist1));
						
						dist4 = sqrt(( (v2[0] - v1[0]) * (v2[0] - v1[0]) ) + ( (v2[1] - v1[1]) * (v2[1] - v1[1]) ));
					
						perc =  (float)(dist2 / dist4);
					
						isect = 32768.0*(perc + 0.0000153);
					
						percent = (float)(isect / 32768.0);
					
						midpoints[numpts] = (1-percent)*eed->v1->co[0] + percent*eed->v2->co[0];
						numpts++;
						midpoints[numpts] = (1-percent)*eed->v1->co[1] + percent*eed->v2->co[1];
						numpts++;
						midpoints[numpts] = (1-percent)*eed->v1->co[2] + percent*eed->v2->co[2];
						numpts++;
							
						eed->f1 = isect;
					}
					else if (mode == 2) {
						/* The following six lines add the coordinates for the midpoint of eed to an array in consecutive order */					
						midpoints[numpts]= (eed->v1->co[0] + eed->v2->co[0])/2.0; 
						numpts++; /* Every time a coordinate is added, the total number of individual coordinates in the array is incremented */
						midpoints[numpts]= (eed->v1->co[1] + eed->v2->co[1])/2.0;
						numpts++;
						midpoints[numpts]= (eed->v1->co[2] + eed->v2->co[2])/2.0;
						numpts++;
					}
					
					/* This if statement ensures that the array is always big enough to hold the midpoint data */
					if(numpts > (midpointblocks*256*3)) { /* Checks to see if index of array is higher than numer of elements in the array */
						temp= midpoints; /* copies data from array to temporary pointer */
			
						midpoints=(float *)MEM_callocN(256*3*sizeof(float)*(midpointblocks+1),"Edge Midpoints"); /* reallocates memory to increase capacity of array */
			
						memcpy(midpoints, temp, midpointblocks*256*3*sizeof(float)); /* copies contents of temp pointer back into array */
			
						midpointblocks++; /* increments number of blocks allocated */
			
						if(temp) MEM_freeN(temp); /* cleans up temp variable */
					}
				
					lastedge=eed;
					eed->f = 1;
		
				}
				else if ((event==ESCKEY) || (event==RIGHTMOUSE)) {
					mode=0;
					mousemove=0;
				}
				else if (event==MIDDLEMOUSE) {
					if(U.flag & VIEWMOVE) {
						if(G.qual==LR_SHIFTKEY) {
							viewmove(0);
						}
						else if (G.qual==LR_CTRLKEY) {
							viewmove(2);
						}
						else if (G.qual==0) {
							viewmove(1);
						}
					}
				}
			}
		}
	
		highlight=0;
		
		screen_swapbuffers();
						
		PIL_sleep_ms(10);
		
	}	
				
	/* send event to redraw this window, does header too */
	addqueue(curarea->win, REDRAW, 1); 
		
	if (mode==1) {
		subdivideflag(1, 0, B_KNIFE|B_PERCENTSUBD);
	}
	else if (mode==2) {
		subdivideflag(1, 0, B_KNIFE);
	}
	
	eed=G.eded.first;
	while(eed){
		eed->f=0;
		eed->f1=0;
		eed=eed->next;
	}						
	
	addqueue(curarea->win,  REDRAW, 0);
	set_cursor(oldcursor);
	if (midpoints) MEM_freeN(midpoints); /* Clears the memory occupied by the array of midpoints */
	
}
--------------030105060304040600060806--