[Bf-blender-cvs] SVN commit: /data/svn/bf-blender [52098] trunk/blender/intern/cycles/util: Fix #32974: cycles curved motion blur is not working well combined with rotation,

Brecht Van Lommel brechtvanlommel at pandora.be
Sun Nov 11 16:02:05 CET 2012


Revision: 52098
          http://projects.blender.org/scm/viewvc.php?view=rev&root=bf-blender&revision=52098
Author:   blendix
Date:     2012-11-11 15:02:05 +0000 (Sun, 11 Nov 2012)
Log Message:
-----------
Fix #32974: cycles curved motion blur is not working well combined with rotation,
problem is that the curved interpolation is not constant speed which leads to
mismatches. Turns out this is really hard to solve and implement efficiently, so
curved motion blur is disabled for now, until I can find a solution.

Modified Paths:
--------------
    trunk/blender/intern/cycles/util/util_transform.cpp
    trunk/blender/intern/cycles/util/util_transform.h

Modified: trunk/blender/intern/cycles/util/util_transform.cpp
===================================================================
--- trunk/blender/intern/cycles/util/util_transform.cpp	2012-11-11 14:53:17 UTC (rev 52097)
+++ trunk/blender/intern/cycles/util/util_transform.cpp	2012-11-11 15:02:05 UTC (rev 52098)
@@ -251,6 +251,13 @@
 	transform_decompose(&decomp->pre, &motion->pre);
 	transform_decompose(&decomp->mid, mid);
 	transform_decompose(&decomp->post, &motion->post);
+
+	/* ensure rotation around shortest angle, negated quaternions are the same
+	 * but this means we don't have to do the check in quat_interpolate */
+	if(dot(decomp->mid.x, decomp->post.x) < 0.0f)
+		decomp->mid.x = -decomp->mid.x;
+	if(dot(decomp->pre.x, decomp->mid.x) < 0.0f)
+		decomp->pre.x = -decomp->pre.x;
 }
 
 CCL_NAMESPACE_END

Modified: trunk/blender/intern/cycles/util/util_transform.h
===================================================================
--- trunk/blender/intern/cycles/util/util_transform.h	2012-11-11 14:53:17 UTC (rev 52097)
+++ trunk/blender/intern/cycles/util/util_transform.h	2012-11-11 15:02:05 UTC (rev 52098)
@@ -39,16 +39,16 @@
 #endif
 } Transform;
 
+/* transform decomposed in rotation/translation/scale. we use the same data
+ * structure as Transform, and tightly pack decomposition into it. first the
+ * rotation (4), then translation (3), then 3x3 scale matrix (9) */
+
 typedef struct MotionTransform {
 	Transform pre;
 	Transform mid;
 	Transform post;
 } MotionTransform;
 
-/* transform decomposed in rotation/translation/scale. we use the same data
- * structure as Transform, and tightly pack decomposition into it. first the
- * rotation (4), then translation (3), then 3x3 scale matrix (9) */
-
 /* Functions */
 
 __device_inline float3 transform_perspective(const Transform *t, const float3 a)
@@ -303,13 +303,11 @@
 
 __device_inline float4 quat_interpolate(float4 q1, float4 q2, float t)
 {
+	/* note: this does not ensure rotation around shortest angle, q1 and q2
+	 * are assumed to be matched already in transform_motion_decompose */
 	float costheta = dot(q1, q2);
 
-	/* rotate around shortest angle */
-	if(costheta < 0.0f) {
-		costheta = -costheta;
-		q1 = -q1;
-	}
+	/* possible optimization: it might be possible to precompute theta/qperp */
 
 	if(costheta > 0.9995f) {
 		/* linear interpolation in degenerate case */
@@ -318,14 +316,17 @@
 	else  {
 		/* slerp */
 		float theta = acosf(clamp(costheta, -1.0f, 1.0f));
+		float4 qperp = normalize(q2 - q1 * costheta);
 		float thetap = theta * t;
-		float4 qperp = normalize(q2 - q1 * costheta);
 		return q1 * cosf(thetap) + qperp * sinf(thetap);
 	}
 }
 
 __device_inline Transform transform_quick_inverse(Transform M)
 {
+	/* possible optimization: can we avoid doing this altogether and construct
+	 * the inverse matrix directly from negated translation, transposed rotation,
+	 * scale can be inverted but what about shearing? */
 	Transform R;
 	float det = M.x.x*(M.z.z*M.y.y - M.z.y*M.y.z) - M.y.x*(M.z.z*M.x.y - M.z.y*M.x.z) + M.z.x*(M.y.z*M.x.y - M.y.y*M.x.z);
 
@@ -380,10 +381,17 @@
 	tfm->w = make_float4(0.0f, 0.0f, 0.0f, 1.0f);
 }
 
+/* Disabled for now, need arc-length parametrization for constant speed motion.
+ * #define CURVED_MOTION_INTERPOLATE */
+
 __device void transform_motion_interpolate(Transform *tfm, const MotionTransform *motion, float t)
 {
+	/* possible optimization: is it worth it adding a check to skip scaling?
+	 * it's probably quite uncommon to have scaling objects. or can we skip
+	 * just shearing perhaps? */
 	Transform decomp;
 
+#ifdef CURVED_MOTION_INTERPOLATE
 	/* 3 point bezier curve interpolation for position */
 	float3 Ppre = float4_to_float3(motion->pre.y);
 	float3 Pmid = float4_to_float3(motion->mid.y);
@@ -395,13 +403,18 @@
 	decomp.y.x = P.x;
 	decomp.y.y = P.y;
 	decomp.y.z = P.z;
+#endif
 
 	/* linear interpolation for rotation and scale */
 	if(t < 0.5f) {
 		t *= 2.0f;
 
 		decomp.x = quat_interpolate(motion->pre.x, motion->mid.x, t);
+#ifdef CURVED_MOTION_INTERPOLATE
 		decomp.y.w = (1.0f - t)*motion->pre.y.w + t*motion->mid.y.w;
+#else
+		decomp.y = (1.0f - t)*motion->pre.y + t*motion->mid.y;
+#endif
 		decomp.z = (1.0f - t)*motion->pre.z + t*motion->mid.z;
 		decomp.w = (1.0f - t)*motion->pre.w + t*motion->mid.w;
 	}
@@ -409,7 +422,11 @@
 		t = (t - 0.5f)*2.0f;
 
 		decomp.x = quat_interpolate(motion->mid.x, motion->post.x, t);
+#ifdef CURVED_MOTION_INTERPOLATE
 		decomp.y.w = (1.0f - t)*motion->mid.y.w + t*motion->post.y.w;
+#else
+		decomp.y = (1.0f - t)*motion->mid.y + t*motion->post.y;
+#endif
 		decomp.z = (1.0f - t)*motion->mid.z + t*motion->post.z;
 		decomp.w = (1.0f - t)*motion->mid.w + t*motion->post.w;
 	}




More information about the Bf-blender-cvs mailing list