[Bf-blender-cvs] [42843004fda] experimental-build: Squashed commit of the staging smooth-curves branch:

Alexander Gavrilov noreply at git.blender.org
Fri Aug 4 09:16:51 CEST 2017


Commit: 42843004fdab789f94b6f25b178aedfdf9b24960
Author: Alexander Gavrilov
Date:   Fri Aug 4 10:15:48 2017 +0300
Branches: experimental-build
https://developer.blender.org/rB42843004fdab789f94b6f25b178aedfdf9b24960

Squashed commit of the staging smooth-curves branch:

commit efa58808d453247664a61e5f2dfe5681acd648b8
Author: Alexander Gavrilov <angavrilov at gmail.com>
Date:   Fri Jul 28 09:07:48 2017 +0300

    Experiment with smoothing color curves yet again.

commit b765d33459076d195c35b942de21a0e53d7624bc
Author: Alexander Gavrilov <angavrilov at gmail.com>
Date:   Sun Jun 4 20:29:17 2017 +0300

    Implement a new automatic handle algorithm to produce smooth F-Curves.

    The legacy algorithm only considers two adjacent points when computing
    the bezier handles, which cannot produce satisfactory results. Animators
    are often forced to manually adjust all curves.

    The new approach instead solves a system of equations to trace a cubic spline
    with continuous second derivative through the whole segment of auto points,
    delimited at ends by keyframes with handles set by other requirements.

    This algorithm also adjusts Vector handles that face ordinary bezier keyframes
    to achieve zero acceleration at the Vector keyframe, instead of simply pointing
    it at the adjacent point.

    Original idea and implementation by Benoit Bolsee <benoit.bolsee at online.be>;
    code mostly rewritten to improve code clarity and extensibility.

commit f037c9a3c8e0a380b397d88c2a58aec5075d07f3
Author: Dalai Felinto <dfelinto at gmail.com>
Date:   Mon Nov 18 16:58:23 2013 -0200

    force fcurve AUTO handlers to use 1/3 of the distance for smoothness
    see: http://www.blender.org/forum/viewtopic.php?p=65508&sid=02e88fe6e3a43338ec8bc354991bc402

    Note: this is also used by the curve code. The magic number 2.5614f
    comes from review 290361776e5858b3903a83c0cddf722b8340e699

commit 7cb409dd6ed3dac92d0861fa5ab8e26da895cf52
Author: Alexander Gavrilov <angavrilov at gmail.com>
Date:   Sun Jun 4 17:15:06 2017 +0300

    Add an FCurve flag to toggle new smoothing behavior.

    The flag is exposed in UI below the curve color selector.

commit 8bd42dc90c2c5f374f0611638b73760cf3905121
Author: Alexander Gavrilov <angavrilov at gmail.com>
Date:   Sun Apr 30 16:14:39 2017 +0300

    Make auto handle placement aware of cyclic extrapolation.

    Cyclic extrapolation is implemented as an f-curve modifier, so this
    technically violates abstraction separation and is something of a hack.
    However without such behavior achieving smooth looping with cyclic
    extrapolation is extremely cumbersome.

    The new behavior is applied when the first modifier is Cyclic
    extrapolation in Repeat or Repeat with Offset mode without
    using influence, repeat count or range restrictions.

    This change in behavior means that curve handles have to be updated
    when the modifier is added, removed or its options change. Due to the
    way code is structured, it seems it requires a helper link to the
    containing curve from the modifier object.

===================================================================

M	source/blender/blenkernel/BKE_curve.h
M	source/blender/blenkernel/BKE_fcurve.h
M	source/blender/blenkernel/intern/colortools.c
M	source/blender/blenkernel/intern/curve.c
M	source/blender/blenkernel/intern/fcurve.c
M	source/blender/blenkernel/intern/fmodifier.c
M	source/blender/blenkernel/intern/ipo.c
M	source/blender/blenkernel/intern/mask.c
M	source/blender/blenkernel/intern/nla.c
M	source/blender/blenlib/BLI_math_solvers.h
M	source/blender/blenlib/intern/math_solvers.c
M	source/blender/blenloader/intern/readfile.c
M	source/blender/editors/animation/drivers.c
M	source/blender/editors/animation/fmodifier_ui.c
M	source/blender/editors/animation/keyframing.c
M	source/blender/editors/curve/editcurve.c
M	source/blender/editors/include/ED_anim_api.h
M	source/blender/editors/interface/interface_templates.c
M	source/blender/editors/object/object_constraint.c
M	source/blender/editors/object/object_relations.c
M	source/blender/editors/space_action/action_edit.c
M	source/blender/editors/space_graph/graph_buttons.c
M	source/blender/editors/space_graph/graph_edit.c
M	source/blender/editors/space_nla/nla_edit.c
M	source/blender/makesdna/DNA_anim_types.h
M	source/blender/makesdna/DNA_color_types.h
M	source/blender/makesdna/DNA_curve_types.h
M	source/blender/makesrna/intern/rna_color.c
M	source/blender/makesrna/intern/rna_fcurve.c

===================================================================

diff --git a/source/blender/blenkernel/BKE_curve.h b/source/blender/blenkernel/BKE_curve.h
index 635e999dd95..c990486b729 100644
--- a/source/blender/blenkernel/BKE_curve.h
+++ b/source/blender/blenkernel/BKE_curve.h
@@ -201,10 +201,13 @@ void BKE_nurb_bpoint_calc_normal(struct Nurb *nu, struct BPoint *bp, float r_nor
 void BKE_nurb_bpoint_calc_plane(struct Nurb *nu, struct BPoint *bp, float r_plane[3]);
 
 void BKE_nurb_handle_calc(struct BezTriple *bezt, struct BezTriple *prev,  struct BezTriple *next,
-                          const bool is_fcurve);
+                          const bool is_fcurve, const bool smoothing);
 void BKE_nurb_handle_calc_simple(struct Nurb *nu, struct BezTriple *bezt);
 void BKE_nurb_handle_calc_simple_auto(struct Nurb *nu, struct BezTriple *bezt);
 
+void BKE_nurb_handle_smooth_fcurve(struct BezTriple *bezt, int total, bool cyclic);
+void BKE_nurb_handle_smooth_color_curve(struct BezTriple *bezt, int total);
+
 void BKE_nurb_handles_calc(struct Nurb *nu);
 void BKE_nurb_handles_autocalc(struct Nurb *nu, int flag);
 void BKE_nurb_bezt_handle_test(struct BezTriple *bezt, const bool use_handle);
diff --git a/source/blender/blenkernel/BKE_fcurve.h b/source/blender/blenkernel/BKE_fcurve.h
index b38f1299763..03328f39c0f 100644
--- a/source/blender/blenkernel/BKE_fcurve.h
+++ b/source/blender/blenkernel/BKE_fcurve.h
@@ -188,7 +188,8 @@ const FModifierTypeInfo *get_fmodifier_typeinfo(const int type);
 
 /* ---------------------- */
 
-struct FModifier *add_fmodifier(ListBase *modifiers, int type);
+struct FModifier *add_fmodifier_raw(ListBase *modifiers, int type);
+struct FModifier *add_fmodifier(struct FCurve *fcu, int type);
 struct FModifier *copy_fmodifier(const struct FModifier *src);
 void copy_fmodifiers(ListBase *dst, const ListBase *src);
 bool remove_fmodifier(ListBase *modifiers, struct FModifier *fcm);
diff --git a/source/blender/blenkernel/intern/colortools.c b/source/blender/blenkernel/intern/colortools.c
index ee0f904c3a6..a5623d54611 100644
--- a/source/blender/blenkernel/intern/colortools.c
+++ b/source/blender/blenkernel/intern/colortools.c
@@ -432,6 +432,9 @@ static void calchandle_curvemap(
 	float len, len_a, len_b;
 	float dvec_a[2], dvec_b[2];
 
+	/* assume normal handle until we check */
+	bezt->f5 = HD_AUTOTYPE_NORMAL;
+
 	if (bezt->h1 == 0 && bezt->h2 == 0) {
 		return;
 	}
@@ -486,6 +489,7 @@ static void calchandle_curvemap(
 					    (ydiff1 >= 0.0f && ydiff2 >= 0.0f))
 					{
 						bezt->vec[0][1] = bezt->vec[1][1];
+						bezt->f5 = HD_AUTOTYPE_SPECIAL;
 					}
 					else { /* handles should not be beyond y coord of two others */
 						if (ydiff1 <= 0.0f) {
@@ -512,6 +516,7 @@ static void calchandle_curvemap(
 					    (ydiff1 >= 0.0f && ydiff2 >= 0.0f))
 					{
 						bezt->vec[2][1] = bezt->vec[1][1];
+						bezt->f5 = HD_AUTOTYPE_SPECIAL;
 					}
 					else { /* handles should not be beyond y coord of two others */
 						if (ydiff1 <= 0.0f) {
@@ -612,45 +617,51 @@ static void curvemap_make_table(CurveMap *cuma, const rctf *clipr)
 		bezt_prev = &bezt[a];
 	}
 	
-	/* first and last handle need correction, instead of pointing to center of next/prev, 
-	 * we let it point to the closest handle */
-	if (cuma->totpoint > 2) {
-		float hlen, nlen, vec[3];
-		
-		if (bezt[0].h2 == HD_AUTO) {
-			
-			hlen = len_v3v3(bezt[0].vec[1], bezt[0].vec[2]); /* original handle length */
-			/* clip handle point */
-			copy_v3_v3(vec, bezt[1].vec[0]);
-			if (vec[0] < bezt[0].vec[1][0])
-				vec[0] = bezt[0].vec[1][0];
-			
-			sub_v3_v3(vec, bezt[0].vec[1]);
-			nlen = len_v3(vec);
-			if (nlen > FLT_EPSILON) {
-				mul_v3_fl(vec, hlen / nlen);
-				add_v3_v3v3(bezt[0].vec[2], vec, bezt[0].vec[1]);
-				sub_v3_v3v3(bezt[0].vec[0], bezt[0].vec[1], vec);
+	if (cuma->flag & CUMA_SMOOTH_HANDLES) {
+		BKE_nurb_handle_smooth_color_curve(bezt, cuma->totpoint);
+	}
+	else {
+		/* first and last handle need correction, instead of pointing to center of next/prev,
+		 * we let it point to the closest handle */
+		if (cuma->totpoint > 2) {
+			float hlen, nlen, vec[3];
+
+			if (bezt[0].h2 == HD_AUTO) {
+
+				hlen = len_v3v3(bezt[0].vec[1], bezt[0].vec[2]); /* original handle length */
+				/* clip handle point */
+				copy_v3_v3(vec, bezt[1].vec[0]);
+				if (vec[0] < bezt[0].vec[1][0])
+					vec[0] = bezt[0].vec[1][0];
+
+				sub_v3_v3(vec, bezt[0].vec[1]);
+				nlen = len_v3(vec);
+				if (nlen > FLT_EPSILON) {
+					mul_v3_fl(vec, hlen / nlen);
+					add_v3_v3v3(bezt[0].vec[2], vec, bezt[0].vec[1]);
+					sub_v3_v3v3(bezt[0].vec[0], bezt[0].vec[1], vec);
+				}
 			}
-		}
-		a = cuma->totpoint - 1;
-		if (bezt[a].h2 == HD_AUTO) {
-			
-			hlen = len_v3v3(bezt[a].vec[1], bezt[a].vec[0]); /* original handle length */
-			/* clip handle point */
-			copy_v3_v3(vec, bezt[a - 1].vec[2]);
-			if (vec[0] > bezt[a].vec[1][0])
-				vec[0] = bezt[a].vec[1][0];
-			
-			sub_v3_v3(vec, bezt[a].vec[1]);
-			nlen = len_v3(vec);
-			if (nlen > FLT_EPSILON) {
-				mul_v3_fl(vec, hlen / nlen);
-				add_v3_v3v3(bezt[a].vec[0], vec, bezt[a].vec[1]);
-				sub_v3_v3v3(bezt[a].vec[2], bezt[a].vec[1], vec);
+			a = cuma->totpoint - 1;
+			if (bezt[a].h2 == HD_AUTO) {
+
+				hlen = len_v3v3(bezt[a].vec[1], bezt[a].vec[0]); /* original handle length */
+				/* clip handle point */
+				copy_v3_v3(vec, bezt[a - 1].vec[2]);
+				if (vec[0] > bezt[a].vec[1][0])
+					vec[0] = bezt[a].vec[1][0];
+
+				sub_v3_v3(vec, bezt[a].vec[1]);
+				nlen = len_v3(vec);
+				if (nlen > FLT_EPSILON) {
+					mul_v3_fl(vec, hlen / nlen);
+					add_v3_v3v3(bezt[a].vec[0], vec, bezt[a].vec[1]);
+					sub_v3_v3v3(bezt[a].vec[2], bezt[a].vec[1], vec);
+				}
 			}
 		}
 	}
+
 	/* make the bezier curve */
 	if (cuma->table)
 		MEM_freeN(cuma->table);
diff --git a/source/blender/blenkernel/intern/curve.c b/source/blender/blenkernel/intern/curve.c
index 7c22a34c7d1..48385b4f456 100644
--- a/source/blender/blenkernel/intern/curve.c
+++ b/source/blender/blenkernel/intern/curve.c
@@ -3137,7 +3137,7 @@ void BKE_curve_bevelList_make(Object *ob, ListBase *nurbs, bool for_render)
 
 static void calchandleNurb_intern(
         BezTriple *bezt, const BezTriple *prev, const BezTriple *next,
-        bool is_fcurve, bool skip_align)
+        bool is_fcurve, bool skip_align, bool fcurve_smoothing)
 {
 	/* defines to avoid confusion */
 #define p2_h1 ((p2) - 3)
@@ -3151,6 +3151,9 @@ static void calchandleNurb_intern(
 	float len_ratio;
 	const float eps = 1e-5;
 
+	/* assume normal handle until we check */
+	bezt->f5 = HD_AUTOTYPE_NORMAL;
+
 	if (bezt->h1 == 0 && bezt->h2 == 0) {
 		return;
 	}
@@ -3202,7 +3205,13 @@ static void calchandleNurb_intern(
 		tvec[2] = dvec_b[2] / len_b + dvec_a[2] / len_a;
 
 		if (is_fcurve) {
-			len = tvec[0];
+			if (fcurve_smoothing) {
+				/* force the handlers transition to be 1/3 */
+				len = 6.0f/2.5614f;
+			}
+			else {
+				len = tvec[0];
+			}
 		}
 		else {
 			len = len_v3(tvec);
@@ -3213,10 +3222,12 @@ static void calchandleNurb_intern(
 			/* only for fcurves */
 			bool leftviolate = false, rightviolate = false;
 
-			if (len_a > 5.0f * len_b)
-				len_a = 5.0f * len_b;
-			if (len_b > 5.0f * len_a)
-				len_b = 5.0f * len_a;
+			if (!is_fcurve || !fcurve_smoothing) {
+				if (len_a > 5.0f * len_b)
+					len_a = 5.0f * len_b;
+				if (len_b > 5.0f * len_a)
+					len_b = 5.0f * len_a;
+			}
 
 			if (ELEM(bezt->h1, HD_AUTO, HD_AUTO_ANIM)) {
 				len_a /= len;
@@ -3227,6 +3238,7 @@ static void calchandleNurb_intern(
 					float ydiff2 = next->vec[1][1] - bezt->vec[1][1];
 					if ((ydiff1 <= 0.0f && ydiff2 <= 0.0f) || (ydiff1 >= 0.0f && ydiff2 >= 0.0f)) {
 						bezt->vec[0][1] = bezt->vec[1][1];
+						bezt->f5 = HD_AUTOTYPE_SPECIAL;
 					}
 					else { /* handles should not be beyond y coord of two others */
 						if (ydiff1 <= 0.0f) {
@@ -3253,6 +3265,7 @@ static void calchandleNurb_intern(
 					float ydiff2 = next->vec[1][1] - bezt->vec[1][1];
 					if ( (ydiff1 <= 0.0f && ydiff2 <= 0.0f) || (ydiff1 >= 0.0f && ydiff2 >= 0.0f) ) {
 						bezt->vec[2][1] = bezt->vec[1][1];
+						bezt->f5 = HD_AUTOTYPE_SPECIAL;
 					}
 					else { /* handles should not be beyond y coord of two others */
 						if (ydiff1 <= 0.0f) {
@@ -3400,7 +3413,7 @@ static void calchandlesNurb_intern(Nurb *nu, bool skip_align)
 	next = bezt + 1;
 
 	while (a--) {
-		calchandleNurb_intern(bezt, prev, next, 0, skip_align);
+		calchandleNurb_intern(bezt, prev, next, 0, skip_align, 0);
 		prev = bezt;
 		if (a == 1) {
 			if (nu->flagu & CU_NURB_CYCLIC)
@@ -3415,9 +3428,1081 @@ static void calchandlesNurb_intern(Nurb *nu, bool skip_align)
 	}
 }
 
-void BKE_nurb_handle_calc(BezTriple *bezt, BezTriple *prev, BezTriple *next, const bool is_fcurve)
+typedef float vec4[4];
+
+static void *allocate_arrays(int count, vec4 ***vectors, float ***floats, char ***chars, const char *name)
+{
+	int num_vectors = 0, num_floats = 0, num_chars = 0;
+
+	while (vectors && vectors[num_vectors]) {
+		num_vectors++;
+	}
+
+	while (floats && floats[num_floats]) {
+		num_floats++;
+	}
+
+	while (chars && chars[num_chars]) {
+		num_chars++;
+	}
+
+	void *buffer = (float*)MEM_mallocN(count * (sizeof(vec4)*num_vectors + sizeof(float)*num_floats + num_chars), name);
+
+	if (!buffer)
+		return NULL;
+
+	vec4 *vptr = buffer;
+
+	for (int i = 0; i < num_vectors; i++, vptr += count)
+		*vectors[i] = vptr;
+
+	float *fptr = (float*)vptr;
+
+	for (int i = 0; i < num_floats; i++, fptr += count)
+		*floats[i] = fptr;
+
+	char *cptr = (char*)fptr;
+
+	for (int i = 0; i < num_chars; i++, cptr += count)
+		*chars[i] = cptr;
+
+	return buffer;
+}
+
+/* computes in which direction to change h[i] to satisfy conditions better */
+static float bezier_relax_direction(float *a, float *b, float *c, float *d, float *h, int i, int count)
+{
+	/* current deviation between sides of the equation */
+	float state = a[i] * h[(i+count-1)%count] + b[i] * h[i] + c[i] * h[(i+1)%count] - d[i];
+
+	/* only the sign is meaningful */
+	return -state * b[i];
+}
+
+static void bezier_lock_unknown(float *a, float *b, float *c, float *d, int i, float value)
+{
+	a[i] = c[i] = 0.0f;
+	b[i] = 1.0f;
+	d[i] = value;
+}
+
+static bool tridiagonal_solve_with_limits(float *a, float *b, float *c, float *d, float *h, float *h

@@ Diff output truncated at 10240 characters. @@




More information about the Bf-blender-cvs mailing list