[Bf-blender-cvs] SVN commit: /data/svn/bf-blender [20214] branches/soc-2009-aligorith/source /blender/blenkernel: NLA Branch: Setting up evaluation system for action strips

Joshua Leung aligorith at gmail.com
Fri May 15 15:23:03 CEST 2009


Revision: 20214
          http://projects.blender.org/plugins/scmsvn/viewcvs.php?view=rev&root=bf-blender&revision=20214
Author:   aligorith
Date:     2009-05-15 15:23:03 +0200 (Fri, 15 May 2009)

Log Message:
-----------
NLA Branch: Setting up evaluation system for action strips

* Refactored F-Curve Modifier stack evaluation into functions which can be reused for F-Curve Modifiers on NLA-Strips 
* Started setting up temporary accumulation buffer system for use when evaluating strips

Modified Paths:
--------------
    branches/soc-2009-aligorith/source/blender/blenkernel/BKE_fcurve.h
    branches/soc-2009-aligorith/source/blender/blenkernel/intern/anim_sys.c
    branches/soc-2009-aligorith/source/blender/blenkernel/intern/fcurve.c

Modified: branches/soc-2009-aligorith/source/blender/blenkernel/BKE_fcurve.h
===================================================================
--- branches/soc-2009-aligorith/source/blender/blenkernel/BKE_fcurve.h	2009-05-15 12:34:01 UTC (rev 20213)
+++ branches/soc-2009-aligorith/source/blender/blenkernel/BKE_fcurve.h	2009-05-15 13:23:03 UTC (rev 20214)
@@ -108,11 +108,15 @@
 void fcurve_copy_modifiers(ListBase *dst, ListBase *src);
 void fcurve_remove_modifier(struct FCurve *fcu, struct FModifier *fcm);
 void fcurve_free_modifiers(struct FCurve *fcu);
-void fcurve_bake_modifiers(struct FCurve *fcu, int start, int end);
 
 struct FModifier *fcurve_find_active_modifier(struct FCurve *fcu);
 void fcurve_set_active_modifier(struct FCurve *fcu, struct FModifier *fcm);
 
+float evaluate_time_fmodifiers(ListBase *modifiers, struct FCurve *fcu, float cvalue, float evaltime);
+void evaluate_value_fmodifiers(ListBase *modifiers, struct FCurve *fcu, float *cvalue, float evaltime);
+
+void fcurve_bake_modifiers(struct FCurve *fcu, int start, int end);
+
 /* ************** F-Curves API ******************** */
 
 /* -------- Data Managemnt  --------  */

Modified: branches/soc-2009-aligorith/source/blender/blenkernel/intern/anim_sys.c
===================================================================
--- branches/soc-2009-aligorith/source/blender/blenkernel/intern/anim_sys.c	2009-05-15 12:34:01 UTC (rev 20213)
+++ branches/soc-2009-aligorith/source/blender/blenkernel/intern/anim_sys.c	2009-05-15 13:23:03 UTC (rev 20214)
@@ -6,6 +6,7 @@
 #include <string.h>
 #include <stddef.h>
 #include <float.h>
+#include <math.h>
 
 #include "MEM_guardedalloc.h"
 
@@ -564,7 +565,7 @@
 typedef struct NlaEvalChannel {
 	struct NlaEvalChannel *next, *prev;
 	
-	PointerRNA *ptr;		/* pointer to struct containing property to use */
+	PointerRNA ptr;			/* pointer to struct containing property to use */
 	PropertyRNA *prop;		/* RNA-property type to use (should be in the struct given) */
 	int index;				/* array index (where applicable) */
 	
@@ -638,13 +639,13 @@
 }
 
 /* evaluate the evaluation time and influence for the strip, storing the results in the strip */
-void nlastrip_evaluate_controls (NlaStrip *strip, float cframe)
+void nlastrip_evaluate_controls (NlaStrip *strip, float ctime)
 {
 	/* firstly, analytically generate values for influence and time (if applicable) */
 	if ((strip->flag & NLASTRIP_FLAG_USR_TIME) == 0)
-		strip->strip_time= nlastrip_get_frame(strip, cframe, 1); /* last arg '1' means current time to 'strip'/action time */
+		strip->strip_time= nlastrip_get_frame(strip, ctime, 1); /* last arg '1' means current time to 'strip'/action time */
 	if ((strip->flag & NLASTRIP_FLAG_USR_INFLUENCE) == 0)
-		strip->influence= nlastrip_get_influence(strip, cframe);
+		strip->influence= nlastrip_get_influence(strip, ctime);
 	
 	/* now strip's evaluate F-Curves for these settings (if applicable) */
 	if (strip->fcurves.first) {
@@ -766,13 +767,104 @@
 
 /* ---------------------- */
 
+/* verify that an appropriate NlaEvalChannel for this F-Curve */
+static NlaEvalChannel *nlaevalchan_verify (PointerRNA *ptr, ListBase *channels, NlaEvalStrip *nes, FCurve *fcu, short *newChan)
+{
+	NlaEvalChannel *nec= NULL;
+	NlaStrip *strip= nes->strip;
+	PropertyRNA *prop;
+	PointerRNA new_ptr;
+	char *path = NULL;
+	short free_path=0;
+	
+	/* sanity checks */
+	if (channels == NULL)
+		return NULL;
+	
+	/* get RNA pointer+property info from F-Curve for more convenient handling */
+		/* get path, remapped as appropriate to work in its new environment */
+	free_path= animsys_remap_path(strip->remap, fcu->rna_path, &path);
+	
+		/* get property to write to */
+	if (RNA_path_resolve(ptr, path, &new_ptr, &prop) == 0)
+		return NULL;
+		/* only ok if animateable */
+	else if (RNA_property_animateable(&new_ptr, prop) == 0) 
+		return NULL;
+	
+	/* loop through existing channels, checking for a channel which affects the same property */
+	for (nec= channels->first; nec; nec= nec->next) {
+		if ((nec->ptr.data == new_ptr.data) && (nec->prop == prop))
+			return nec;
+	}
+	
+	/* allocate a new struct for this */
+	nec= MEM_callocN(sizeof(NlaEvalChannel), "NlaEvalChannel");
+	*newChan= 1;
+	BLI_addtail(channels, nec);
+	
+	nec->ptr= new_ptr; 
+	nec->prop= prop;
+	nec->index= fcu->array_index;
+	
+	return nec;
+}
+
+/* ---------------------- */
+
+/* evaluate action-clip strip */
+static void nlastrip_evaluate_actionclip (PointerRNA *ptr, ListBase *channels, NlaEvalStrip *nes)
+{
+	NlaStrip *strip= nes->strip;
+	FCurve *fcu;
+	float evaltime;
+	
+	/* evaluate strip's modifiers which modify time to evaluate the base curves at */
+	evaltime= evaluate_time_fmodifiers(&strip->modifiers, NULL, 0.0f, strip->strip_time);
+	
+	/* evaluate all the F-Curves in the action, saving the relevant pointers to data that will need to be used */
+	for (fcu= strip->act->curves.first; fcu; fcu= fcu->next) {
+		NlaEvalChannel *nec;
+		float value = 0.0f;
+		short newChan = -1;
+		
+		/* check if this curve should be skipped */
+		if (fcu->flag & (FCURVE_MUTED|FCURVE_DISABLED)) 
+			continue;
+			
+		/* evaluate the F-Curve's value for the time given in the strip 
+		 * NOTE: we use the modified time here, since strip's F-Curve Modifiers are applied on top of this 
+		 */
+		value= evaluate_fcurve(fcu, evaltime);
+		
+		/* apply strip's F-Curve Modifiers on this value 
+		 * NOTE: we apply the strip's original evaluation time not the modified one (as per standard F-Curve eval)
+		 */
+		evaluate_value_fmodifiers(&strip->modifiers, fcu, &value, strip->strip_time);
+		
+		
+		/* get an NLA evaluation channel to work with, and accumulate the evaluated value with the value(s)
+		 * stored in this channel if it has been used already
+		 */
+		nec= nlaevalchan_verify(ptr, channels, nes, fcu, &newChan);
+		//if (nec)
+		//	nlaevalchan_accumulate(ptr, nec, nes, newChan, value);
+	}
+}
+
 /* evaluates the given evaluation strip */
-// FIXME: will we need the evaluation cache table set up to blend stuff in?
 // TODO: only evaluate here, but flush in one go using the accumulated channels at end...
-static void nlastrip_ctime_evaluate (ListBase *channels, NlaEvalStrip *nes, float ctime)
+static void nlastrip_evaluate (PointerRNA *ptr, ListBase *channels, NlaEvalStrip *nes)
 {
-	// 1. (in old code) was to extract 'IPO-channels' from actions
-	// 2. blend between the 'accumulated' data, and the new data
+	/* actions to take depend on the type of strip */
+	switch (nes->strip->type) {
+		case NLASTRIP_TYPE_CLIP: /* action-clip */
+			nlastrip_evaluate_actionclip(ptr, channels, nes);
+			break;
+		case NLASTRIP_TYPE_TRANSITION: /* transition */
+			// XXX code this...
+			break;
+	}
 }
 
 /* write the accumulated settings to */
@@ -807,7 +899,7 @@
 	
 	/* 2. for each strip, evaluate then accumulate on top of existing channels, but don't set values yet */
 	for (nes= estrips.first; nes; nes= nes->next) 
-		nlastrip_ctime_evaluate(&echannels, nes, ctime);
+		nlastrip_evaluate(ptr, &echannels, nes);
 	
 	/* 3. flush effects of accumulating channels in NLA to the actual data they affect */
 	nladata_flush_channels(ptr, &echannels);

Modified: branches/soc-2009-aligorith/source/blender/blenkernel/intern/fcurve.c
===================================================================
--- branches/soc-2009-aligorith/source/blender/blenkernel/intern/fcurve.c	2009-05-15 12:34:01 UTC (rev 20213)
+++ branches/soc-2009-aligorith/source/blender/blenkernel/intern/fcurve.c	2009-05-15 13:23:03 UTC (rev 20214)
@@ -2166,34 +2166,6 @@
 	}
 }
 
-/* Bake modifiers for given F-Curve to curve sample data, in the frame range defined
- * by start and end (inclusive).
- */
-void fcurve_bake_modifiers (FCurve *fcu, int start, int end)
-{
-	ChannelDriver *driver;
-	
-	/* sanity checks */
-	// TODO: make these tests report errors using reports not printf's
-	if ELEM(NULL, fcu, fcu->modifiers.first) {
-		printf("Error: No F-Curve with F-Curve Modifiers to Bake\n");
-		return;
-	}
-	
-	/* temporarily, disable driver while we sample, so that they don't influence the outcome */
-	driver= fcu->driver;
-	fcu->driver= NULL;
-	
-	/* bake the modifiers, by sampling the curve at each frame */
-	fcurve_store_samples(fcu, NULL, start, end, fcurve_samplingcb_evalcurve);
-	
-	/* free the modifiers now */
-	fcurve_free_modifiers(fcu);
-	
-	/* restore driver */
-	fcu->driver= driver;
-}
-
 /* Find the active F-Curve Modifier */
 FModifier *fcurve_find_active_modifier (FCurve *fcu)
 {
@@ -2231,6 +2203,98 @@
 		fcm->flag |= FMODIFIER_FLAG_ACTIVE;
 }
 
+/* Evaluation API --------------------------- */
+
+/* evaluate time modifications imposed by some F-Curve Modifiers
+ *	- this step acts as an optimisation to prevent the F-Curve stack being evaluated 
+ *	  several times by modifiers requesting the time be modified, as the final result
+ *	  would have required using the modified time
+ *	- modifiers only ever recieve the unmodified time, as subsequent modifiers should be
+ *	  working on the 'global' result of the modified curve, not some localised segment,
+ *	  so nevaltime gets set to whatever the last time-modifying modifier likes...
+ *	- we start from the end of the stack, as only the last one matters for now
+ */
+float evaluate_time_fmodifiers (ListBase *modifiers, FCurve *fcu, float cvalue, float evaltime)
+{
+	FModifier *fcm;
+	float m_evaltime= evaltime;
+	
+	/* sanity checks */
+	if ELEM(NULL, modifiers, modifiers->first)
+		return evaltime;
+		
+	/* find the first modifier from end of stack that modifies time, and calculate the time the modifier
+	 * would calculate time at
+	 */
+	for (fcm= fcu->modifiers.last; fcm; fcm= fcm->prev) {
+		FModifierTypeInfo *fmi= fmodifier_get_typeinfo(fcm);
+		
+		/* only evaluate if there's a callback for this */
+		// TODO: implement the 'influence' control feature...
+		if (fmi && fmi->evaluate_modifier_time) {
+			if ((fcm->flag & (FMODIFIER_FLAG_DISABLED|FMODIFIER_FLAG_MUTED)) == 0)
+				m_evaltime= fmi->evaluate_modifier_time(fcu, fcm, cvalue, evaltime);
+			break;
+		}
+	}
+	
+	/* return the modified evaltime */
+	return m_evaltime;
+}
+
+/* Evalautes the given set of F-Curve Modifiers using the given data
+ * Should only be called after evaluate_time_fmodifiers() has been called...
+ */
+void evaluate_value_fmodifiers (ListBase *modifiers, FCurve *fcu, float *cvalue, float evaltime)
+{
+	FModifier *fcm;
+	
+	/* sanity checks */
+	if ELEM(NULL, modifiers, modifiers->first)
+		return;
+	

@@ Diff output truncated at 10240 characters. @@




More information about the Bf-blender-cvs mailing list