Cycles: motion blur is now curved and passes exactly through the midpoint.
authorBrecht Van Lommel <brechtvanlommel@pandora.be>
Wed, 17 Oct 2012 12:55:23 +0000 (12:55 +0000)
committerBrecht Van Lommel <brechtvanlommel@pandora.be>
Wed, 17 Oct 2012 12:55:23 +0000 (12:55 +0000)
Previously it would only interpolate between the previous and next frame,
which meant it might not hit the current frame position.

intern/cycles/kernel/kernel_object.h
intern/cycles/kernel/kernel_types.h
intern/cycles/render/camera.cpp
intern/cycles/render/nodes.cpp
intern/cycles/render/object.cpp
intern/cycles/util/util_transform.cpp
intern/cycles/util/util_transform.h

index 602574cb73628910230521aae0ec97197380f9a3..79ff7e2020afe7a6ddfc88a7282e7a37bae003a1 100644 (file)
@@ -23,8 +23,9 @@ enum ObjectTransform {
        OBJECT_INVERSE_TRANSFORM = 3,
        OBJECT_PROPERTIES = 6,
        OBJECT_TRANSFORM_MOTION_PRE = 8,
-       OBJECT_TRANSFORM_MOTION_POST = 12,
-       OBJECT_DUPLI = 16
+       OBJECT_TRANSFORM_MOTION_MID = 12,
+       OBJECT_TRANSFORM_MOTION_POST = 16,
+       OBJECT_DUPLI = 18
 };
 
 __device_inline Transform object_fetch_transform(KernelGlobals *kg, int object, enum ObjectTransform type)
@@ -59,11 +60,15 @@ __device_inline Transform object_fetch_transform_motion(KernelGlobals *kg, int o
                motion.pre.z = kernel_tex_fetch(__objects, offset + 2);
                motion.pre.w = kernel_tex_fetch(__objects, offset + 3);
 
+               motion.mid.x = kernel_tex_fetch(__objects, offset + 4);
+               motion.mid.y = kernel_tex_fetch(__objects, offset + 5);
+               motion.mid.z = kernel_tex_fetch(__objects, offset + 6);
+               motion.mid.w = kernel_tex_fetch(__objects, offset + 7);
 
-               motion.post.x = kernel_tex_fetch(__objects, offset + 4);
-               motion.post.y = kernel_tex_fetch(__objects, offset + 5);
-               motion.post.z = kernel_tex_fetch(__objects, offset + 6);
-               motion.post.w = kernel_tex_fetch(__objects, offset + 7);
+               motion.post.x = kernel_tex_fetch(__objects, offset + 8);
+               motion.post.y = kernel_tex_fetch(__objects, offset + 9);
+               motion.post.z = kernel_tex_fetch(__objects, offset + 10);
+               motion.post.w = kernel_tex_fetch(__objects, offset + 11);
 
                transform_motion_interpolate(&tfm, &motion, time);
 
index bcf80cb76fb956abfe3870542861ad7b8e85e4b1..4cf414091f545da0565e6a1ad53d24c77eb8d368 100644 (file)
@@ -29,7 +29,7 @@
 CCL_NAMESPACE_BEGIN
 
 /* constants */
-#define OBJECT_SIZE            18
+#define OBJECT_SIZE            22
 #define LIGHT_SIZE                     4
 #define FILTER_TABLE_SIZE      256
 #define RAMP_TABLE_SIZE                256
index 727b9801d95ff7e504b74fd358ff0c8480756b41..7703d0cbc8e5f08d9c7ddf87670491eadee002c3 100644 (file)
@@ -197,9 +197,8 @@ void Camera::device_update(Device *device, DeviceScene *dscene, Scene *scene)
        }
 #ifdef __CAMERA_MOTION__
        else if(need_motion == Scene::MOTION_BLUR) {
-               /* todo: exact camera position will not be hit this way */
                if(use_motion) {
-                       transform_motion_decompose(&kcam->motion, &motion);
+                       transform_motion_decompose(&kcam->motion, &motion, &matrix);
                        kcam->have_motion = 1;
                }
        }
index 0bd24f71930f9e38d9625f84e1117fa6b222cd79..ef139d994da9d23398efc461b0f55384d5bdf81d 100644 (file)
@@ -1254,8 +1254,6 @@ void WardBsdfNode::attributes(AttributeRequestSet *attributes)
 
 void WardBsdfNode::compile(SVMCompiler& compiler)
 {
-       ShaderInput *tangent_in = input("Tangent");
-
        BsdfNode::compile(compiler, input("Roughness U"), input("Roughness V"));
 }
 
index f5d78c080c859abeadf3bdf48e9a61a92f437cec..63e904511e625a8598c2e22311d5ffe4f7a0b55e 100644 (file)
@@ -57,7 +57,7 @@ void Object::compute_bounds(bool motion_blur)
 
        if(motion_blur && use_motion) {
                MotionTransform decomp;
-               transform_motion_decompose(&decomp, &motion);
+               transform_motion_decompose(&decomp, &motion, &tfm);
 
                bounds = BoundBox::empty;
 
@@ -219,7 +219,7 @@ void ObjectManager::device_update_transforms(Device *device, DeviceScene *dscene
                                mtfm_post = mtfm_post * itfm;
 
                        memcpy(&objects[offset+8], &mtfm_pre, sizeof(float4)*4);
-                       memcpy(&objects[offset+12], &mtfm_post, sizeof(float4)*4);
+                       memcpy(&objects[offset+16], &mtfm_post, sizeof(float4)*4);
                }
 #ifdef __OBJECT_MOTION__
                else if(need_motion == Scene::MOTION_BLUR) {
@@ -227,21 +227,21 @@ void ObjectManager::device_update_transforms(Device *device, DeviceScene *dscene
                                /* decompose transformations for interpolation */
                                MotionTransform decomp;
 
-                               transform_motion_decompose(&decomp, &ob->motion);
-                               memcpy(&objects[offset+8], &decomp, sizeof(float4)*8);
+                               transform_motion_decompose(&decomp, &ob->motion, &ob->tfm);
+                               memcpy(&objects[offset+8], &decomp, sizeof(float4)*12);
                                flag |= SD_OBJECT_MOTION;
                                have_motion = true;
                        }
                        else {
                                float4 no_motion = make_float4(FLT_MAX);
-                               memcpy(&objects[offset+8], &no_motion, sizeof(float4));
+                               memcpy(&objects[offset+8], &no_motion, sizeof(float4)*12);
                        }
                }
 #endif
 
                /* dupli object coords */
-               objects[offset+16] = make_float4(ob->dupli_generated[0], ob->dupli_generated[1], ob->dupli_generated[2], 0.0f);
-               objects[offset+17] = make_float4(ob->dupli_uv[0], ob->dupli_uv[1], 0.0f, 0.0f);
+               objects[offset+20] = make_float4(ob->dupli_generated[0], ob->dupli_generated[1], ob->dupli_generated[2], 0.0f);
+               objects[offset+21] = make_float4(ob->dupli_uv[0], ob->dupli_uv[1], 0.0f, 0.0f);
 
                /* object flag */
                if(ob->use_holdout)
index b3c6506dfa015a7bed74c541c6bf65895ded22ae..70ee13d96d7196185e22d03d81a54337f3c45bb9 100644 (file)
@@ -246,9 +246,10 @@ static void transform_decompose(Transform *decomp, const Transform *tfm)
        decomp->w = make_float4(scale.y.z, scale.z.x, scale.z.y, scale.z.z);
 }
 
-void transform_motion_decompose(MotionTransform *decomp, const MotionTransform *motion)
+void transform_motion_decompose(MotionTransform *decomp, const MotionTransform *motion, const Transform *mid)
 {
        transform_decompose(&decomp->pre, &motion->pre);
+       transform_decompose(&decomp->mid, mid);
        transform_decompose(&decomp->post, &motion->post);
 }
 
index 3d6aefed56da01aaf79a0ae9137b164185fc407c..df5255422079f2492f0caabe5502c8d166e91656 100644 (file)
@@ -41,6 +41,7 @@ typedef struct Transform {
 
 typedef struct MotionTransform {
        Transform pre;
+       Transform mid;
        Transform post;
 } MotionTransform;
 
@@ -383,11 +384,37 @@ __device void transform_motion_interpolate(Transform *tfm, const MotionTransform
 {
        Transform decomp;
 
-       decomp.x = quat_interpolate(motion->pre.x, motion->post.x, t);
-       decomp.y = (1.0f - t)*motion->pre.y + t*motion->post.y;
-       decomp.z = (1.0f - t)*motion->pre.z + t*motion->post.z;
-       decomp.w = (1.0f - t)*motion->pre.w + t*motion->post.w;
+       /* 3 point bezier curve interpolation for position */
+       float3 Ppre = float4_to_float3(motion->pre.y);
+       float3 Pmid = float4_to_float3(motion->mid.y);
+       float3 Ppost = float4_to_float3(motion->post.y);
 
+       float3 Pcontrol = 2.0f*Pmid - 0.5f*(Ppre + Ppost);
+       float3 P = Ppre*t*t + Pcontrol*2.0f*t*(1.0f - t) + Ppost*(1.0f - t)*(1.0f - t);
+
+       decomp.y.x = P.x;
+       decomp.y.y = P.y;
+       decomp.y.z = P.z;
+
+       /* linear interpolation for rotation and scale */
+       if(t < 0.5f) {
+               t *= 2.0f;
+
+               decomp.x = quat_interpolate(motion->pre.x, motion->mid.x, t);
+               decomp.y.w = (1.0f - t)*motion->pre.y.w + t*motion->mid.y.w;
+               decomp.z = (1.0f - t)*motion->pre.z + t*motion->mid.z;
+               decomp.w = (1.0f - t)*motion->pre.w + t*motion->mid.w;
+       }
+       else {
+               t = (t - 0.5f)*2.0f;
+
+               decomp.x = quat_interpolate(motion->mid.x, motion->post.x, t);
+               decomp.y.w = (1.0f - t)*motion->mid.y.w + t*motion->post.y.w;
+               decomp.z = (1.0f - t)*motion->mid.z + t*motion->post.z;
+               decomp.w = (1.0f - t)*motion->mid.w + t*motion->post.w;
+       }
+
+       /* compose rotation, translation, scale into matrix */
        transform_compose(tfm, &decomp);
 }
 
@@ -398,7 +425,7 @@ __device_inline bool operator==(const MotionTransform& A, const MotionTransform&
        return (A.pre == B.pre && A.post == B.post);
 }
 
-void transform_motion_decompose(MotionTransform *decomp, const MotionTransform *motion);
+void transform_motion_decompose(MotionTransform *decomp, const MotionTransform *motion, const Transform *mid);
 
 #endif