Beispiel #1
0
/* helper func - just draw the F-Curve by sampling the visible region (for drawing curves with modifiers) */
static void draw_fcurve_curve(bAnimContext *ac, ID *id, FCurve *fcu, View2D *v2d, View2DGrid *grid)
{
	ChannelDriver *driver;
	float samplefreq, ctime;
	float stime, etime;
	float unitFac;
	float dx, dy;
	short mapping_flag = ANIM_get_normalization_flags(ac);

	/* when opening a blend file on a different sized screen or while dragging the toolbar this can happen
	 * best just bail out in this case */
	UI_view2d_grid_size(grid, &dx, &dy);
	if (dx <= 0.0f)
		return;


	/* disable any drivers temporarily */
	driver = fcu->driver;
	fcu->driver = NULL;
	
	/* compute unit correction factor */
	unitFac = ANIM_unit_mapping_get_factor(ac->scene, id, fcu, mapping_flag);
	
	/* Note about sampling frequency:
	 *  Ideally, this is chosen such that we have 1-2 pixels = 1 segment
	 *	which means that our curves can be as smooth as possible. However,
	 *  this does mean that curves may not be fully accurate (i.e. if they have
	 *  sudden spikes which happen at the sampling point, we may have problems).
	 *  Also, this may introduce lower performance on less densely detailed curves,'
	 *	though it is impossible to predict this from the modifiers!
	 *
	 *	If the automatically determined sampling frequency is likely to cause an infinite
	 *	loop (i.e. too close to 0), then clamp it to a determined "safe" value. The value
	 *  chosen here is just the coarsest value which still looks reasonable...
	 */
	/* grid->dx represents the number of 'frames' between gridlines, but we divide by U.v2d_min_gridsize to get pixels-steps */
	/* TODO: perhaps we should have 1.0 frames as upper limit so that curves don't get too distorted? */
	samplefreq = dx / (U.v2d_min_gridsize * U.pixelsize);
	if (samplefreq < 0.00001f) samplefreq = 0.00001f;
	
	
	/* the start/end times are simply the horizontal extents of the 'cur' rect */
	stime = v2d->cur.xmin;
	etime = v2d->cur.xmax + samplefreq; /* + samplefreq here so that last item gets included... */
	
	
	/* at each sampling interval, add a new vertex 
	 *	- apply the unit correction factor to the calculated values so that 
	 *	  the displayed values appear correctly in the viewport
	 */
	glBegin(GL_LINE_STRIP);
	
	for (ctime = stime; ctime <= etime; ctime += samplefreq)
		glVertex2f(ctime, evaluate_fcurve(fcu, ctime) * unitFac);
	
	glEnd();
	
	/* restore driver */
	fcu->driver = driver;
}
Beispiel #2
0
/* Evaluates the curves between each selected keyframe on each frame, and keys the value  */
void sample_fcurve (FCurve *fcu)
{
	BezTriple *bezt, *start=NULL, *end=NULL;
	tempFrameValCache *value_cache, *fp;
	int sfra, range;
	int i, n, nIndex;
	
	/* find selected keyframes... once pair has been found, add keyframes  */
	for (i=0, bezt=fcu->bezt; i < fcu->totvert; i++, bezt++) {
		/* check if selected, and which end this is */
		if (BEZSELECTED(bezt)) {
			if (start) {
				/* set end */
				end= bezt;
				
				/* cache values then add keyframes using these values, as adding
				 * keyframes while sampling will affect the outcome...
				 *	- only start sampling+adding from index=1, so that we don't overwrite original keyframe
				 */
				range= (int)( ceil(end->vec[1][0] - start->vec[1][0]) );
				sfra= (int)( floor(start->vec[1][0]) );
				
				if (range) {
					value_cache= MEM_callocN(sizeof(tempFrameValCache)*range, "IcuFrameValCache");
					
					/* 	sample values 	*/
					for (n=1, fp=value_cache; n<range && fp; n++, fp++) {
						fp->frame= (float)(sfra + n);
						fp->val= evaluate_fcurve(fcu, fp->frame);
					}
					
					/* 	add keyframes with these, tagging as 'breakdowns' 	*/
					for (n=1, fp=value_cache; n<range && fp; n++, fp++) {
						nIndex= insert_vert_fcurve(fcu, fp->frame, fp->val, 1);
						BEZKEYTYPE(fcu->bezt + nIndex)= BEZT_KEYTYPE_BREAKDOWN;
					}
					
					/* free temp cache */
					MEM_freeN(value_cache);
					
					/* as we added keyframes, we need to compensate so that bezt is at the right place */
					bezt = fcu->bezt + i + range - 1;
					i += (range - 1);
				}
				
				/* bezt was selected, so it now marks the start of a whole new chain to search */
				start= bezt;
				end= NULL;
			}
			else {
				/* just set start keyframe */
				start= bezt;
				end= NULL;
			}
		}
	}
	
	/* recalculate channel's handles? */
	calchandles_fcurve(fcu);
}
Beispiel #3
0
/* helper call for drawing influence/time control curves for a given NLA-strip */
static void nla_draw_strip_curves(NlaStrip *strip, float yminc, float ymaxc)
{
	const float yheight = ymaxc - yminc;
	
	/* drawing color is simply a light-gray */
	// TODO: is this color suitable?
	// XXX nasty hacked color for now... which looks quite bad too...
	glColor3f(0.7f, 0.7f, 0.7f);
	
	/* draw with AA'd line */
	glEnable(GL_LINE_SMOOTH);
	glEnable(GL_BLEND);
	
	/* influence -------------------------- */
	if (strip->flag & NLASTRIP_FLAG_USR_INFLUENCE) {
		FCurve *fcu = list_find_fcurve(&strip->fcurves, "influence", 0);
		float cfra;
		
		/* plot the curve (over the strip's main region) */
		glBegin(GL_LINE_STRIP);
		/* sample at 1 frame intervals, and draw
		 *	- min y-val is yminc, max is y-maxc, so clamp in those regions
		 */
		for (cfra = strip->start; cfra <= strip->end; cfra += 1.0f) {
			float y = evaluate_fcurve(fcu, cfra);
			CLAMP(y, 0.0f, 1.0f);
			glVertex2f(cfra, ((y * yheight) + yminc));
		}
		glEnd(); // GL_LINE_STRIP
	}
	else {
		/* use blend in/out values only if both aren't zero */
		if ((IS_EQF(strip->blendin, 0.0f) && IS_EQF(strip->blendout, 0.0f)) == 0) {
			glBegin(GL_LINE_STRIP);
			/* start of strip - if no blendin, start straight at 1, otherwise from 0 to 1 over blendin frames */
			if (IS_EQF(strip->blendin, 0.0f) == 0) {
				glVertex2f(strip->start,                    yminc);
				glVertex2f(strip->start + strip->blendin,   ymaxc);
			}
			else
				glVertex2f(strip->start, ymaxc);
					
			/* end of strip */
			if (IS_EQF(strip->blendout, 0.0f) == 0) {
				glVertex2f(strip->end - strip->blendout,    ymaxc);
				glVertex2f(strip->end,                      yminc);
			}
			else
				glVertex2f(strip->end, ymaxc);
			glEnd(); // GL_LINE_STRIP
		}
	}
	
	/* time -------------------------- */
	// XXX do we want to draw this curve? in a different color too?
	
	/* turn off AA'd lines */
	glDisable(GL_LINE_SMOOTH);
	glDisable(GL_BLEND);
}
/* Create new libmv Tracks structure from blender's tracks list. */
static struct libmv_Tracks *libmv_tracks_new(MovieClip *clip, ListBase *tracksbase, int width, int height)
{
	int tracknr = 0;
	MovieTrackingTrack *track;
	struct libmv_Tracks *tracks = libmv_tracksNew();

	track = tracksbase->first;
	while (track) {
		FCurve *weight_fcurve;
		int a = 0;

		weight_fcurve = id_data_find_fcurve(&clip->id, track, &RNA_MovieTrackingTrack,
		                                    "weight", 0, NULL);

		for (a = 0; a < track->markersnr; a++) {
			MovieTrackingMarker *marker = &track->markers[a];

			if ((marker->flag & MARKER_DISABLED) == 0) {
				float weight = track->weight;

				if (weight_fcurve) {
					int scene_framenr =
						BKE_movieclip_remap_clip_to_scene_frame(clip, marker->framenr);
					weight = evaluate_fcurve(weight_fcurve, scene_framenr);
				}

				libmv_tracksInsert(tracks, marker->framenr, tracknr,
				                   (marker->pos[0] + track->offset[0]) * width,
				                   (marker->pos[1] + track->offset[1]) * height,
				                   weight);
			}
		}

		track = track->next;
		tracknr++;
	}

	return tracks;
}
Beispiel #5
0
/* helper func - just draw the F-Curve by sampling the visible region (for drawing curves with modifiers) */
static void draw_fcurve_curve(bAnimContext *ac, ID *id, FCurve *fcu, View2D *v2d, View2DGrid *grid)
{
	SpaceIpo *sipo = (SpaceIpo *)ac->sl;
	ChannelDriver *driver;
	float samplefreq;
	float stime, etime;
	float unitFac, offset;
	float dx, dy;
	short mapping_flag = ANIM_get_normalization_flags(ac);
	int i, n;

	/* when opening a blend file on a different sized screen or while dragging the toolbar this can happen
	 * best just bail out in this case */
	UI_view2d_grid_size(grid, &dx, &dy);
	if (dx <= 0.0f)
		return;


	/* disable any drivers temporarily */
	driver = fcu->driver;
	fcu->driver = NULL;
	
	/* compute unit correction factor */
	unitFac = ANIM_unit_mapping_get_factor(ac->scene, id, fcu, mapping_flag, &offset);
	
	/* Note about sampling frequency:
	 *  Ideally, this is chosen such that we have 1-2 pixels = 1 segment
	 *	which means that our curves can be as smooth as possible. However,
	 *  this does mean that curves may not be fully accurate (i.e. if they have
	 *  sudden spikes which happen at the sampling point, we may have problems).
	 *  Also, this may introduce lower performance on less densely detailed curves,
	 *	though it is impossible to predict this from the modifiers!
	 *
	 *	If the automatically determined sampling frequency is likely to cause an infinite
	 *	loop (i.e. too close to 0), then clamp it to a determined "safe" value. The value
	 *  chosen here is just the coarsest value which still looks reasonable...
	 */
	/* grid->dx represents the number of 'frames' between gridlines, but we divide by U.v2d_min_gridsize to get pixels-steps */
	/* TODO: perhaps we should have 1.0 frames as upper limit so that curves don't get too distorted? */
	samplefreq = dx / (U.v2d_min_gridsize * U.pixelsize);
	
	if (sipo->flag & SIPO_BEAUTYDRAW_OFF) {
		/* Low Precision = coarse lower-bound clamping
		 * 
		 * Although the "Beauty Draw" flag was originally for AA'd
		 * line drawing, the sampling rate here has a much greater
		 * impact on performance (e.g. for T40372)!
		 *
		 * This one still amounts to 10 sample-frames for each 1-frame interval
		 * which should be quite a decent approximation in many situations.
		 */
		if (samplefreq < 0.1f)
			samplefreq = 0.1f;
	}
	else {
		/* "Higher Precision" but slower - especially on larger windows (e.g. T40372) */
		if (samplefreq < 0.00001f)
			samplefreq = 0.00001f;
	}
	
	
	/* the start/end times are simply the horizontal extents of the 'cur' rect */
	stime = v2d->cur.xmin;
	etime = v2d->cur.xmax + samplefreq; /* + samplefreq here so that last item gets included... */
	
	
	/* at each sampling interval, add a new vertex 
	 *	- apply the unit correction factor to the calculated values so that 
	 *	  the displayed values appear correctly in the viewport
	 */
	glBegin(GL_LINE_STRIP);
	
	n = (etime - stime) / samplefreq + 0.5f;
	for (i = 0; i <= n; i++) {
		float ctime = stime + i * samplefreq;
		glVertex2f(ctime, (evaluate_fcurve(fcu, ctime) + offset) * unitFac);
	}
	
	glEnd();
	
	/* restore driver */
	fcu->driver = driver;
}
Beispiel #6
0
/* helper for apply() - perform sliding for quaternion rotations (using quat blending) */
static void pose_slide_apply_quat(tPoseSlideOp *pso, tPChanFCurveLink *pfl)
{
	FCurve *fcu_w = NULL, *fcu_x = NULL, *fcu_y = NULL, *fcu_z = NULL;
	bPoseChannel *pchan = pfl->pchan;
	LinkData *ld = NULL;
	char *path = NULL;
	float cframe;
	
	/* get the path to use - this should be quaternion rotations only (needs care) */
	path = BLI_sprintfN("%s.%s", pfl->pchan_path, "rotation_quaternion");
	
	/* get the current frame number */
	cframe = (float)pso->cframe;
	
	/* using this path, find each matching F-Curve for the variables we're interested in */
	while ( (ld = poseAnim_mapping_getNextFCurve(&pfl->fcurves, ld, path)) ) {
		FCurve *fcu = (FCurve *)ld->data;
		
		/* assign this F-Curve to one of the relevant pointers... */
		switch (fcu->array_index) {
			case 3: /* z */
				fcu_z = fcu;
				break;
			case 2: /* y */
				fcu_y = fcu;
				break;
			case 1: /* x */
				fcu_x = fcu;
				break;
			case 0: /* w */
				fcu_w = fcu;
				break;
		}
	}
	
	/* only if all channels exist, proceed */
	if (fcu_w && fcu_x && fcu_y && fcu_z) {
		float quat_prev[4], quat_next[4];
		
		/* get 2 quats */
		quat_prev[0] = evaluate_fcurve(fcu_w, pso->prevFrame);
		quat_prev[1] = evaluate_fcurve(fcu_x, pso->prevFrame);
		quat_prev[2] = evaluate_fcurve(fcu_y, pso->prevFrame);
		quat_prev[3] = evaluate_fcurve(fcu_z, pso->prevFrame);
		
		quat_next[0] = evaluate_fcurve(fcu_w, pso->nextFrame);
		quat_next[1] = evaluate_fcurve(fcu_x, pso->nextFrame);
		quat_next[2] = evaluate_fcurve(fcu_y, pso->nextFrame);
		quat_next[3] = evaluate_fcurve(fcu_z, pso->nextFrame);
		
		/* perform blending */
		if (pso->mode == POSESLIDE_BREAKDOWN) {
			/* just perform the interpol between quat_prev and quat_next using pso->percentage as a guide */
			interp_qt_qtqt(pchan->quat, quat_prev, quat_next, pso->percentage);
		}
		else if (pso->mode == POSESLIDE_PUSH) {
			float quat_diff[4], quat_orig[4];

			/* calculate the delta transform from the previous to the current */
			/* TODO: investigate ways to favour one transform more? */
			sub_qt_qtqt(quat_diff, pchan->quat, quat_prev);

			/* make a copy of the original rotation */
			copy_qt_qt(quat_orig, pchan->quat);
			
			/* increase the original by the delta transform, by an amount determined by percentage */
			add_qt_qtqt(pchan->quat, quat_orig, quat_diff, pso->percentage);
		}
		else {
			float quat_interp[4], quat_orig[4];
			int iters = (int)ceil(10.0f * pso->percentage); /* TODO: maybe a sensitivity ctrl on top of this is needed */

			/* perform this blending several times until a satisfactory result is reached */
			while (iters-- > 0) {
				/* calculate the interpolation between the endpoints */
				interp_qt_qtqt(quat_interp, quat_prev, quat_next, (cframe - pso->prevFrame) / (pso->nextFrame - pso->prevFrame));
				
				/* make a copy of the original rotation */
				copy_qt_qt(quat_orig, pchan->quat);
				
				/* tricky interpolations - blending between original and new */
				interp_qt_qtqt(pchan->quat, quat_orig, quat_interp, 1.0f / 6.0f);
			}
		}
	}
	
	/* free the path now */
	MEM_freeN(path);
}
Beispiel #7
0
/* helper for apply() - perform sliding for some value */
static void pose_slide_apply_val(tPoseSlideOp *pso, FCurve *fcu, float *val)
{
	float cframe = (float)pso->cframe;
	float sVal, eVal;
	float w1, w2;
	
	/* get keyframe values for endpoint poses to blend with */
	/* previous/start */
	sVal = evaluate_fcurve(fcu, (float)pso->prevFrame);
	/* next/end */
	eVal = evaluate_fcurve(fcu, (float)pso->nextFrame);
	
	/* calculate the relative weights of the endpoints */
	if (pso->mode == POSESLIDE_BREAKDOWN) {
		/* get weights from the percentage control */
		w1 = pso->percentage;    /* this must come second */
		w2 = 1.0f - w1;          /* this must come first */
	}
	else {
		/*	- these weights are derived from the relative distance of these 
		 *	  poses from the current frame
		 *	- they then get normalized so that they only sum up to 1
		 */
		float wtot; 
		
		w1 = cframe - (float)pso->prevFrame;
		w2 = (float)pso->nextFrame - cframe;
		
		wtot = w1 + w2;
		w1 = (w1 / wtot);
		w2 = (w2 / wtot);
	}
	
	/* depending on the mode, calculate the new value
	 *	- in all of these, the start+end values are multiplied by w2 and w1 (respectively),
	 *	  since multiplication in another order would decrease the value the current frame is closer to
	 */
	switch (pso->mode) {
		case POSESLIDE_PUSH: /* make the current pose more pronounced */
		{
			/* perform a weighted average here, favoring the middle pose
			 *	- numerator should be larger than denominator to 'expand' the result
			 *	- perform this weighting a number of times given by the percentage...
			 */
			int iters = (int)ceil(10.0f * pso->percentage); /* TODO: maybe a sensitivity ctrl on top of this is needed */

			while (iters-- > 0) {
				(*val) = (-((sVal * w2) + (eVal * w1)) + ((*val) * 6.0f) ) / 5.0f;
			}
			break;
		}
		case POSESLIDE_RELAX: /* make the current pose more like its surrounding ones */
		{
			/* perform a weighted average here, favoring the middle pose
			 *	- numerator should be smaller than denominator to 'relax' the result
			 *	- perform this weighting a number of times given by the percentage...
			 */
			int iters = (int)ceil(10.0f * pso->percentage); /* TODO: maybe a sensitivity ctrl on top of this is needed */

			while (iters-- > 0) {
				(*val) = ( ((sVal * w2) + (eVal * w1)) + ((*val) * 5.0f) ) / 6.0f;
			}
			break;
		}
		case POSESLIDE_BREAKDOWN: /* make the current pose slide around between the endpoints */
		{
			/* perform simple linear interpolation - coefficient for start must come from pso->percentage... */
			/* TODO: make this use some kind of spline interpolation instead? */
			(*val) = ((sVal * w2) + (eVal * w1));
			break;
		}
	}
}
Beispiel #8
0
/* helper call for drawing influence/time control curves for a given NLA-strip */
static void nla_draw_strip_curves(NlaStrip *strip, float yminc, float ymaxc, unsigned int pos)
{
  const float yheight = ymaxc - yminc;

  immUniformColor3f(0.7f, 0.7f, 0.7f);

  /* draw with AA'd line */
  GPU_line_smooth(true);
  GPU_blend(true);

  /* influence -------------------------- */
  if (strip->flag & NLASTRIP_FLAG_USR_INFLUENCE) {
    FCurve *fcu = list_find_fcurve(&strip->fcurves, "influence", 0);
    float cfra;

    /* plot the curve (over the strip's main region) */
    if (fcu) {
      immBegin(GPU_PRIM_LINE_STRIP, abs((int)(strip->end - strip->start) + 1));

      /* sample at 1 frame intervals, and draw
       * - min y-val is yminc, max is y-maxc, so clamp in those regions
       */
      for (cfra = strip->start; cfra <= strip->end; cfra += 1.0f) {
        float y = evaluate_fcurve(fcu, cfra); /* assume this to be in 0-1 range */
        CLAMP(y, 0.0f, 1.0f);
        immVertex2f(pos, cfra, ((y * yheight) + yminc));
      }

      immEnd();
    }
  }
  else {
    /* use blend in/out values only if both aren't zero */
    if ((IS_EQF(strip->blendin, 0.0f) && IS_EQF(strip->blendout, 0.0f)) == 0) {
      immBeginAtMost(GPU_PRIM_LINE_STRIP, 4);

      /* start of strip - if no blendin, start straight at 1,
       * otherwise from 0 to 1 over blendin frames */
      if (IS_EQF(strip->blendin, 0.0f) == 0) {
        immVertex2f(pos, strip->start, yminc);
        immVertex2f(pos, strip->start + strip->blendin, ymaxc);
      }
      else {
        immVertex2f(pos, strip->start, ymaxc);
      }

      /* end of strip */
      if (IS_EQF(strip->blendout, 0.0f) == 0) {
        immVertex2f(pos, strip->end - strip->blendout, ymaxc);
        immVertex2f(pos, strip->end, yminc);
      }
      else {
        immVertex2f(pos, strip->end, ymaxc);
      }

      immEnd();
    }
  }

  /* turn off AA'd lines */
  GPU_line_smooth(false);
  GPU_blend(false);
}