[Bf-blender-cvs] SVN commit: /data/svn/bf-blender [17217] branches/animsys2/source/blender/ src/drawipo.c: AnimSys2: IPO Drawing-Code (Part 1 of Cleanup)

Joshua Leung aligorith at gmail.com
Wed Oct 29 12:25:14 CET 2008


Revision: 17217
          http://projects.blender.org/plugins/scmsvn/viewcvs.php?view=rev&root=bf-blender&revision=17217
Author:   aligorith
Date:     2008-10-29 12:25:14 +0100 (Wed, 29 Oct 2008)

Log Message:
-----------
AnimSys2: IPO Drawing-Code (Part 1 of Cleanup)

Started cleaning up the drawing-code for IPO-curves.
* draw_ipocurves() has been cleaned up, with the inner loops being split out into two separate helper functions. The same will need to be done with some of the other functions too.

* Removed the ugly global pickselcode. This was only used in this file under certain conditions, so it seems fine to remove it. 

* Usual formatting and commenting tweaks to make this code less intimidating. This is in preparation for some future work on IPO-curves...

Modified Paths:
--------------
    branches/animsys2/source/blender/src/drawipo.c

Modified: branches/animsys2/source/blender/src/drawipo.c
===================================================================
--- branches/animsys2/source/blender/src/drawipo.c	2008-10-29 11:20:02 UTC (rev 17216)
+++ branches/animsys2/source/blender/src/drawipo.c	2008-10-29 11:25:14 UTC (rev 17217)
@@ -1341,237 +1341,297 @@
 	}
 }
 
-int pickselcode;
-
-static void init_pickselcode(void)
+/* draw one repeat of an ipo-curve - bitflag curve only (this is evil stuff to expose to user like this) */
+static void draw_ipocurve_repeat_bits (IpoCurve *icu, float cycxofs)
 {
-	pickselcode= 1;
+	BezTriple *bezt= icu->bezt;
+	int a;
+	
+	/* loop over each keyframe, drawing a line extending from that point */
+	for (a=0, bezt=icu->bezt; a < icu->totvert; a++, bezt++) {
+		int val= (int)bezt->vec[1][1];
+		int b= 0;
+		
+		/* for each bit in the int, draw a line if the keyframe incorporates it */
+		for (b = 0; b < 31; b++) {
+			if (val & (1<<b)) {
+				float v1[2];
+				
+				/* value stays constant */
+				v1[1]= b+1;
+				
+				glBegin(GL_LINE_STRIP);
+					/* extend left too if first keyframe, and not cyclic extrapolation */
+					if ((a == 0) && !(icu->extrap & IPO_CYCL)) {
+						v1[0]= G.v2d->cur.xmin+cycxofs;
+						glVertex2fv(v1);
+					}
+					
+					/* must pass through current keyframe */
+					v1[0]= bezt->vec[1][0] + cycxofs;
+					glVertex2fv(v1); 
+					
+					/* 1. if there is a next keyframe, extend until then OR
+					 * 2. extend until 'infinity' if not cyclic extrapolation
+					 */
+					if ((a+1) < icu->totvert) v1[0]= (bezt+1)->vec[1][0]+cycxofs;
+					else if ((icu->extrap & IPO_CYCL)==0) v1[0]= G.v2d->cur.xmax+cycxofs;
+					
+					glVertex2fv(v1);
+				glEnd();
+			}
+		}
+	}
 }
 
+/* draw one repeat of an ipo-curve - normal curve */
+static void draw_ipocurve_repeat_normal (IpoCurve *icu, float cycxofs, float cycyofs, float *facp)
+{
+	BezTriple *prevbezt= icu->bezt;
+	BezTriple *bezt= prevbezt+1;
+	float v1[2], v2[2], v3[2], v4[2];
+	float *fp, data[120];
+	float fac= *(facp);
+	int b= icu->totvert-1;
+	int resol;
+	
+	glBegin(GL_LINE_STRIP);
+	
+	/* extrapolate to left? */
+	if ((icu->extrap & IPO_CYCL)==0) {
+		/* left-side of view comes before first keyframe, so need to extend as not cyclic */
+		if (prevbezt->vec[1][0] > G.v2d->cur.xmin) {
+			v1[0]= G.v2d->cur.xmin;
+			
+			/* y-value depends on the interpolation */
+			if ((icu->extrap==IPO_HORIZ) || (icu->ipo==IPO_CONST) || (icu->totvert==1)) {
+				/* just extend across the first keyframe's value */
+				v1[1]= prevbezt->vec[1][1];
+			} 
+			else if (icu->ipo==IPO_LIN) {
+				/* extrapolate linear dosnt use the handle, use the next points center instead */
+				fac= (prevbezt->vec[1][0]-bezt->vec[1][0])/(prevbezt->vec[1][0]-v1[0]);
+				if (fac) fac= 1.0f/fac;
+				v1[1]= prevbezt->vec[1][1]-fac*(prevbezt->vec[1][1]-bezt->vec[1][1]);
+			} 
+			else {
+				/* based on angle of handle 1 (relative to keyframe) */
+				fac= (prevbezt->vec[0][0]-prevbezt->vec[1][0])/(prevbezt->vec[1][0]-v1[0]);
+				if (fac) fac= 1.0f/fac;
+				v1[1]= prevbezt->vec[1][1]-fac*(prevbezt->vec[0][1]-prevbezt->vec[1][1]);
+			}
+			
+			glVertex2fv(v1);
+		}
+	}
+	
+	/* if only one keyframe, add it now */
+	if (icu->totvert == 1) {
+		v1[0]= prevbezt->vec[1][0] + cycxofs;
+		v1[1]= prevbezt->vec[1][1] + cycyofs;
+		glVertex2fv(v1);
+	}
+	
+	/* draw curve between first and last keyframe (if there are enough to do so) */
+	while (b--) {
+		// TODO: per segment interpolation still needs to be added here...
+		if (icu->ipo==IPO_CONST) {
+			/* Constant-Interpolation: draw segment between previous keyframe and next, but holding same value */
+			v1[0]= prevbezt->vec[1][0]+cycxofs;
+			v1[1]= prevbezt->vec[1][1]+cycyofs;
+			glVertex2fv(v1);
+			
+			v1[0]= bezt->vec[1][0]+cycxofs;
+			v1[1]= prevbezt->vec[1][1]+cycyofs;
+			glVertex2fv(v1);
+		}
+		else if (icu->ipo==IPO_LIN) {
+			/* Linear interpolation: just add one point (which should add a new line segment) */
+			v1[0]= prevbezt->vec[1][0]+cycxofs;
+			v1[1]= prevbezt->vec[1][1]+cycyofs;
+			glVertex2fv(v1);
+		}
+		else {
+			/* Bezier-Interpolation: draw curve as series of segments between keyframes 
+			 *	- resol determines number of points to sample in between keyframes
+			 */
+			
+			/* resol not depending on horizontal resolution anymore, drivers for example... */
+			if (icu->driver) 
+				resol= 32;
+			else 
+				resol= 3.0*sqrt(bezt->vec[1][0] - prevbezt->vec[1][0]);
+			
+			if (resol < 2) {
+				/* only draw one */
+				v1[0]= prevbezt->vec[1][0]+cycxofs;
+				v1[1]= prevbezt->vec[1][1]+cycyofs;
+				glVertex2fv(v1);
+			}
+			else {
+				/* clamp resolution to max of 32 */
+				if (resol > 32) resol= 32;
+				
+				v1[0]= prevbezt->vec[1][0]+cycxofs;
+				v1[1]= prevbezt->vec[1][1]+cycyofs;
+				v2[0]= prevbezt->vec[2][0]+cycxofs;
+				v2[1]= prevbezt->vec[2][1]+cycyofs;
+				
+				v3[0]= bezt->vec[0][0]+cycxofs;
+				v3[1]= bezt->vec[0][1]+cycyofs;
+				v4[0]= bezt->vec[1][0]+cycxofs;
+				v4[1]= bezt->vec[1][1]+cycyofs;
+				
+				correct_bezpart(v1, v2, v3, v4);
+				
+				forward_diff_bezier(v1[0], v2[0], v3[0], v4[0], data, resol, 3);
+				forward_diff_bezier(v1[1], v2[1], v3[1], v4[1], data+1, resol, 3);
+				
+				for (fp= data; resol; resol--, fp+= 3)
+					glVertex2fv(fp);
+			}
+		}
+		
+		/* get next pointers */
+		prevbezt= bezt; 
+		bezt++;
+		
+		/* last point? */
+		if (b == 0) {
+			v1[0]= prevbezt->vec[1][0]+cycxofs;
+			v1[1]= prevbezt->vec[1][1]+cycyofs;
+			glVertex2fv(v1);
+		}
+	}
+	
+	/* extrapolate to right? (see code for left-extrapolation above too) */
+	if ((icu->extrap & IPO_CYCL)==0) {
+		if(prevbezt->vec[1][0] < G.v2d->cur.xmax) {
+			v1[0]= G.v2d->cur.xmax;
+			
+			/* y-value depends on the interpolation */
+			if ((icu->extrap==IPO_HORIZ) || (icu->ipo==IPO_CONST) || (icu->totvert==1)) {
+				/* based on last keyframe's value */
+				v1[1]= prevbezt->vec[1][1];
+			} 
+			else if (icu->ipo==IPO_LIN) {
+				/* extrapolate linear dosnt use the handle, use the previous points center instead */
+				bezt = prevbezt-1;
+				fac= (prevbezt->vec[1][0]-bezt->vec[1][0])/(prevbezt->vec[1][0]-v1[0]);
+				if (fac) fac= 1.0f/fac;
+				v1[1]= prevbezt->vec[1][1]-fac*(prevbezt->vec[1][1]-bezt->vec[1][1]);
+			} 
+			else {
+				/* based on angle of handle 1 (relative to keyframe) */
+				fac= (prevbezt->vec[2][0]-prevbezt->vec[1][0])/(prevbezt->vec[1][0]-v1[0]);
+				if (fac) fac= 1.0f/fac;
+				v1[1]= prevbezt->vec[1][1]-fac*(prevbezt->vec[2][1]-prevbezt->vec[1][1]);
+			}
+			
+			glVertex2fv(v1);
+		}
+	}
+	
+	glEnd();
+	
+	/* return fac, as we alter it */
+	*(facp) = fac;
+} 
+
+/* draw all ipo-curves */
 static void draw_ipocurves(int sel)
 {
 	EditIpo *ei;
-	IpoCurve *icu;
-	BezTriple *bezt, *prevbezt;
-	float *fp, fac, data[120], v1[2], v2[2], v3[2], v4[2];
-	float cycdx=0, cycdy=0, cycxofs, cycyofs;
-	int a, b, resol, cycount, val, nr;
+	int nr, val, pickselcode=0;
 	
+	/* if we're drawing for GL_SELECT, reset pickselcode first 
+	 * 	- there's only one place that will do this, so it should be fine
+	 */
+	if (G.f & G_PICKSEL)
+		pickselcode= 1;
 	
 	ei= G.sipo->editipo;
-	for(nr=0; nr<G.sipo->totipo; nr++, ei++) {
+	for (nr=0; nr<G.sipo->totipo; nr++, ei++) {
 		if ISPOIN3(ei, flag & IPO_VISIBLE, icu, icu->bezt) {
-			
-			if(G.f & G_PICKSEL) {
+			/* val is used to indicate if curve can be edited */
+			if (G.f & G_PICKSEL) {
+				/* when using OpenGL to select stuff (on mouseclick) */
 				glLoadName(pickselcode++);
 				val= 1;
 			}
 			else {
-				val= (ei->flag & (IPO_SELECT+IPO_EDIT))!=0;
+				/* filter to only draw those that are selected or unselected (based on drawing mode */
+				val= (ei->flag & (IPO_SELECT+IPO_EDIT)) != 0;
 				val= (val==sel);
 			}
 			
-			if(val) {
+			/* only draw those curves that we can draw */
+			if (val) {
+				IpoCurve *icu= ei->icu;
+				float cycdx=0.0f, cycdy=0.0f, cycxofs=0.0f, cycyofs=0.0f;
+				const int lastindex= (icu->totvert-1);
+				float fac= 0.0f;
+				int cycount=1;
 				
-				cycyofs= cycxofs= 0.0;
-				cycount= 1;
-				
-				icu= ei->icu;	
-				
-				/* curve */
-				if(G.sipo->showkey) BIF_ThemeColor(TH_TEXT); 
+				/* set color for curve curve:
+				 *	- bitflag curves (evil) must always be drawn coloured as they cannot work with IPO-Keys
+				 *	- when IPO-Keys are shown, individual curves are not editable, so we show by drawing them all black
+				 */
+				if ((G.sipo->showkey) && (ei->disptype!=IPO_DISPBITS)) BIF_ThemeColor(TH_TEXT); 
 				else cpack(ei->col);
 				
-				/* cyclic */
-				if(icu->extrap & IPO_CYCL) {
-					cycdx= (icu->bezt+icu->totvert-1)->vec[1][0] - icu->bezt->vec[1][0];
-					cycdy= (icu->bezt+icu->totvert-1)->vec[1][1] - icu->bezt->vec[1][1];
-					if(cycdx>0.01) {
-						
-						while(icu->bezt->vec[1][0]+cycxofs > G.v2d->cur.xmin) {
-							cycxofs-= cycdx;
-							if(icu->extrap & IPO_DIR) cycyofs-= cycdy;
+				/* cyclic curves - get offset and number of repeats to display */
+				if (icu->extrap & IPO_CYCL) {
+					BezTriple *bezt= icu->bezt;
+					BezTriple *lastbezt= bezt + lastindex;
+					
+					/* calculate cycle length and amplitude  */
+					cycdx= lastbezt->vec[1][0] - bezt->vec[1][0];
+					cycdy= lastbezt->vec[1][1] - bezt->vec[1][1];
+					
+					/* check that the cycle does have some length */
+					if (cycdx > 0.01) {
+						/* count cycles before first frame  */
+						while (icu->bezt->vec[1][0]+cycxofs > G.v2d->cur.xmin) {
+							cycxofs -= cycdx;
+							if (icu->extrap & IPO_DIR) cycyofs-= cycdy;
 							cycount++;
 						}
-						bezt= icu->bezt+(icu->totvert-1);
-						fac= 0.0;
-						while(bezt->vec[1][0]+fac < G.v2d->cur.xmax) {
+						
+						/* count cycles after last frame (and adjust offset) */
+						fac= 0.0f;
+						while (lastbezt->vec[1][0]+fac < G.v2d->cur.xmax) {
 							cycount++;
-							fac+= cycdx;
+							fac += cycdx;
 						}
 					}
 				}
 				
-				while(cycount--) {
+				/* repeat process for each repeat */
+				while (cycount--) {
+					/* bitflag curves are drawn differently to normal curves */
+					if (ei->disptype==IPO_DISPBITS)
+						draw_ipocurve_repeat_bits(icu, cycxofs);
+					else
+						draw_ipocurve_repeat_normal(icu, cycxofs, cycyofs, &fac);
 					
-					if(ei->disptype==IPO_DISPBITS) {
-						
-						/* lines */
-						cpack(ei->col);
-						bezt= icu->bezt;
-						a= icu->totvert;
-						
-						while(a--) {
-							val= bezt->vec[1][1];
-							b= 0;
-							
-							while(b<31) {
-								if(val & (1<<b)) {
-									v1[1]= b+1;
-									
-									glBegin(GL_LINE_STRIP);

@@ Diff output truncated at 10240 characters. @@




More information about the Bf-blender-cvs mailing list