Cycles: support animated object scale in motion blur.
authorStefan Werner <stefan.werner@tangent-animation.com>
Sat, 2 Dec 2017 02:28:13 +0000 (03:28 +0100)
committerBrecht Van Lommel <brechtvanlommel@gmail.com>
Thu, 11 Jan 2018 01:58:29 +0000 (02:58 +0100)
This was disabled previously due to CUDA compiler bugs, see T32900.

Differential Revision: https://developer.blender.org/D2937

intern/cycles/kernel/geom/geom_attribute.h
intern/cycles/kernel/geom/geom_object.h
intern/cycles/kernel/kernel_camera.h
intern/cycles/kernel/kernel_types.h
intern/cycles/render/camera.cpp
intern/cycles/render/object.cpp
intern/cycles/util/util_transform.cpp
intern/cycles/util/util_transform.h

index 18f5c81..c72595e 100644 (file)
@@ -53,7 +53,7 @@ ccl_device_inline AttributeDescriptor attribute_not_found()
 
 ccl_device_inline uint object_attribute_map_offset(KernelGlobals *kg, int object)
 {
-       int offset = object*OBJECT_SIZE + 11;
+       int offset = object*OBJECT_SIZE + 15;
        float4 f = kernel_tex_fetch(__objects, offset);
        return __float_as_uint(f.y);
 }
index a276096..d77c40f 100644 (file)
@@ -28,11 +28,12 @@ CCL_NAMESPACE_BEGIN
 
 enum ObjectTransform {
        OBJECT_TRANSFORM = 0,
-       OBJECT_TRANSFORM_MOTION_PRE = 0,
        OBJECT_INVERSE_TRANSFORM = 4,
-       OBJECT_TRANSFORM_MOTION_POST = 4,
-       OBJECT_PROPERTIES = 8,
-       OBJECT_DUPLI = 9
+       OBJECT_TRANSFORM_MOTION_PRE = 0,
+       OBJECT_TRANSFORM_MOTION_MID = 4,
+       OBJECT_TRANSFORM_MOTION_POST = 8,
+       OBJECT_PROPERTIES = 12,
+       OBJECT_DUPLI = 13
 };
 
 enum ObjectVectorTransform {
@@ -90,19 +91,24 @@ ccl_device_inline Transform object_fetch_vector_transform(KernelGlobals *kg, int
 #ifdef __OBJECT_MOTION__
 ccl_device_inline Transform object_fetch_transform_motion(KernelGlobals *kg, int object, float time)
 {
-       DecompMotionTransform motion;
+       MotionTransform motion;
 
        int offset = object*OBJECT_SIZE + (int)OBJECT_TRANSFORM_MOTION_PRE;
 
-       motion.mid.x = kernel_tex_fetch(__objects, offset + 0);
-       motion.mid.y = kernel_tex_fetch(__objects, offset + 1);
-       motion.mid.z = kernel_tex_fetch(__objects, offset + 2);
-       motion.mid.w = kernel_tex_fetch(__objects, offset + 3);
+       motion.pre.x = kernel_tex_fetch(__objects, offset + 0);
+       motion.pre.y = kernel_tex_fetch(__objects, offset + 1);
+       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.pre_x = kernel_tex_fetch(__objects, offset + 4);
-       motion.pre_y = kernel_tex_fetch(__objects, offset + 5);
-       motion.post_x = kernel_tex_fetch(__objects, offset + 6);
-       motion.post_y = 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 tfm;
        transform_motion_interpolate(&tfm, &motion, time);
@@ -328,7 +334,7 @@ ccl_device_inline uint object_patch_map_offset(KernelGlobals *kg, int object)
        if(object == OBJECT_NONE)
                return 0;
 
-       int offset = object*OBJECT_SIZE + 11;
+       int offset = object*OBJECT_SIZE + 15;
        float4 f = kernel_tex_fetch(__objects, offset);
        return __float_as_uint(f.x);
 }
index 0df5217..77e3446 100644 (file)
@@ -95,11 +95,11 @@ ccl_device void camera_sample_perspective(KernelGlobals *kg, float raster_x, flo
 #  ifdef __KERNEL_OPENCL__
                const MotionTransform tfm = kernel_data.cam.motion;
                transform_motion_interpolate(&cameratoworld,
-                                            ((const DecompMotionTransform*)&tfm),
+                                                                        &tfm,
                                             ray->time);
 #  else
                transform_motion_interpolate(&cameratoworld,
-                                            ((const DecompMotionTransform*)&kernel_data.cam.motion),
+                                            &kernel_data.cam.motion,
                                             ray->time);
 #  endif
        }
@@ -207,11 +207,11 @@ ccl_device void camera_sample_orthographic(KernelGlobals *kg, float raster_x, fl
 #  ifdef __KERNEL_OPENCL__
                const MotionTransform tfm = kernel_data.cam.motion;
                transform_motion_interpolate(&cameratoworld,
-                                            (const DecompMotionTransform*)&tfm,
+                                            &tfm,
                                             ray->time);
 #  else
                transform_motion_interpolate(&cameratoworld,
-                                            (const DecompMotionTransform*)&kernel_data.cam.motion,
+                                            &kernel_data.cam.motion,
                                             ray->time);
 #  endif
        }
@@ -285,11 +285,11 @@ ccl_device_inline void camera_sample_panorama(KernelGlobals *kg,
 #  ifdef __KERNEL_OPENCL__
                const MotionTransform tfm = kernel_data.cam.motion;
                transform_motion_interpolate(&cameratoworld,
-                                            (const DecompMotionTransform*)&tfm,
+                                            &tfm,
                                             ray->time);
 #  else
                transform_motion_interpolate(&cameratoworld,
-                                            (const DecompMotionTransform*)&kernel_data.cam.motion,
+                                            &kernel_data.cam.motion,
                                             ray->time);
 #  endif
        }
index c4a9b3f..b052d66 100644 (file)
@@ -35,7 +35,7 @@
 CCL_NAMESPACE_BEGIN
 
 /* Constants */
-#define OBJECT_SIZE            12
+#define OBJECT_SIZE            16
 #define OBJECT_VECTOR_SIZE     6
 #define LIGHT_SIZE             11
 #define FILTER_TABLE_SIZE      1024
index 83ff8a1..9b22614 100644 (file)
@@ -353,7 +353,7 @@ void Camera::device_update(Device *device, DeviceScene *dscene, Scene *scene)
 #ifdef __CAMERA_MOTION__
        else if(need_motion == Scene::MOTION_BLUR) {
                if(use_motion) {
-                       transform_motion_decompose((DecompMotionTransform*)&kcam->motion, &motion, &matrix);
+                       transform_motion_decompose(&kcam->motion, &motion, &matrix);
                        kcam->have_motion = 1;
                }
                if(use_perspective_motion) {
index d7143f2..380c12f 100644 (file)
@@ -97,7 +97,7 @@ void Object::compute_bounds(bool motion_blur)
                        mtfm.post = tfm;
                }
 
-               DecompMotionTransform decomp;
+               MotionTransform decomp;
                transform_motion_decompose(&decomp, &mtfm, &tfm);
 
                bounds = BoundBox::empty;
@@ -365,7 +365,7 @@ void ObjectManager::device_update_object_transform(UpdateObejctTransformState *s
        /* OBJECT_INVERSE_TRANSFORM */
        memcpy(&objects[offset+4], &itfm, sizeof(float4)*3);
        /* OBJECT_PROPERTIES */
-       objects[offset+8] = make_float4(surface_area, pass_id, random_number, __int_as_float(particle_index));
+       objects[offset+12] = make_float4(surface_area, pass_id, random_number, __int_as_float(particle_index));
 
        if(mesh->use_motion_blur) {
                state->have_motion = true;
@@ -402,10 +402,10 @@ void ObjectManager::device_update_object_transform(UpdateObejctTransformState *s
        else if(state->need_motion == Scene::MOTION_BLUR) {
                if(ob->use_motion) {
                        /* decompose transformations for interpolation. */
-                       DecompMotionTransform decomp;
+                       MotionTransform decomp;
 
                        transform_motion_decompose(&decomp, &ob->motion, &ob->tfm);
-                       memcpy(&objects[offset], &decomp, sizeof(float4)*8);
+                       memcpy(&objects[offset], &decomp, sizeof(float4)*12);
                        flag |= SD_OBJECT_MOTION;
                        state->have_motion = true;
                }
@@ -418,9 +418,9 @@ void ObjectManager::device_update_object_transform(UpdateObejctTransformState *s
        int numverts = mesh->verts.size();
        int numkeys = mesh->curve_keys.size();
 
-       objects[offset+9] = make_float4(ob->dupli_generated[0], ob->dupli_generated[1], ob->dupli_generated[2], __int_as_float(numkeys));
-       objects[offset+10] = make_float4(ob->dupli_uv[0], ob->dupli_uv[1], __int_as_float(numsteps), __int_as_float(numverts));
-       objects[offset+11] = make_float4(0.0f, 0.0f, 0.0f, 0.0f);
+       objects[offset+13] = make_float4(ob->dupli_generated[0], ob->dupli_generated[1], ob->dupli_generated[2], __int_as_float(numkeys));
+       objects[offset+14] = make_float4(ob->dupli_uv[0], ob->dupli_uv[1], __int_as_float(numsteps), __int_as_float(numverts));
+       objects[offset+15] = make_float4(0.0f, 0.0f, 0.0f, 0.0f);
 
        /* Object flag. */
        if(ob->use_holdout) {
@@ -655,7 +655,7 @@ void ObjectManager::device_update_mesh_offsets(Device *, DeviceScene *dscene, Sc
 
        foreach(Object *object, scene->objects) {
                Mesh* mesh = object->mesh;
-               int offset = object_index*OBJECT_SIZE + 11;
+               int offset = object_index*OBJECT_SIZE + 15;
 
                if(mesh->patch_table) {
                        uint patch_map_offset = 2*(mesh->patch_table_offset + mesh->patch_table->total_size() -
index b8f182a..c127054 100644 (file)
@@ -247,30 +247,18 @@ 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(DecompMotionTransform *decomp, const MotionTransform *motion, const Transform *mid)
+void transform_motion_decompose(MotionTransform *decomp, const MotionTransform *motion, const Transform *mid)
 {
-       Transform pre, post;
-
-       transform_decompose(&pre, &motion->pre);
+       transform_decompose(&decomp->pre, &motion->pre);
        transform_decompose(&decomp->mid, mid);
-       transform_decompose(&post, &motion->post);
+       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, post.x) < 0.0f)
+       if(dot(decomp->pre.x, decomp->mid.x) < 0.0f)
+               decomp->pre.x = -decomp->pre.x;
+       if(dot(decomp->mid.x, decomp->post.x) < 0.0f)
                decomp->mid.x = -decomp->mid.x;
-       if(dot(pre.x, decomp->mid.x) < 0.0f)
-               pre.x = -pre.x;
-       
-       /* drop scale of pre/post */
-       pre.y.w = decomp->mid.y.w;
-       post.y.w = decomp->mid.y.w;
-
-       /* store translation/rotation part of pre/post */
-       decomp->pre_x = pre.x;
-       decomp->pre_y = pre.y;
-       decomp->post_x = post.x;
-       decomp->post_y = post.y;
 }
 
 Transform transform_from_viewplane(BoundBox2D& viewplane)
index aef168c..ac0804a 100644 (file)
@@ -39,9 +39,7 @@ typedef struct 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).
- *
- * For the DecompMotionTransform we drop scale from pre/post. */
+ * rotation (4), then translation (3), then 3x3 scale matrix (9). */
 
 typedef struct ccl_may_alias MotionTransform {
        Transform pre;
@@ -49,12 +47,6 @@ typedef struct ccl_may_alias MotionTransform {
        Transform post;
 } MotionTransform;
 
-typedef struct DecompMotionTransform {
-       Transform mid;
-       float4 pre_x, pre_y;
-       float4 post_x, post_y;
-} DecompMotionTransform;
-
 typedef struct PerspectiveMotionTransform {
        Transform pre;
        Transform post;
@@ -466,7 +458,7 @@ ccl_device_inline void transform_compose(Transform *tfm, const Transform *decomp
 /* Disabled for now, need arc-length parametrization for constant speed motion.
  * #define CURVED_MOTION_INTERPOLATE */
 
-ccl_device void transform_motion_interpolate(Transform *tfm, const DecompMotionTransform *motion, float t)
+ccl_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
@@ -475,9 +467,9 @@ ccl_device void transform_motion_interpolate(Transform *tfm, const DecompMotionT
 
 #ifdef CURVED_MOTION_INTERPOLATE
        /* 3 point bezier curve interpolation for position */
-       float3 Ppre = float4_to_float3(motion->pre_y);
+       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 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);
@@ -491,27 +483,28 @@ ccl_device void transform_motion_interpolate(Transform *tfm, const DecompMotionT
        if(t < 0.5f) {
                t *= 2.0f;
 
-               decomp.x = quat_interpolate(motion->pre_x, motion->mid.x, t);
+               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;
+               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;
+               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;
        }
        else {
                t = (t - 0.5f)*2.0f;
 
-               decomp.x = quat_interpolate(motion->mid.x, motion->post_x, t);
+               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;
+               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;
+               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;
        }
 
-       decomp.z = motion->mid.z;
-       decomp.w = motion->mid.w;
-
        /* compose rotation, translation, scale into matrix */
        transform_compose(tfm, &decomp);
 }
@@ -526,7 +519,7 @@ ccl_device_inline bool operator==(const MotionTransform& A, const MotionTransfor
 }
 
 float4 transform_to_quat(const Transform& tfm);
-void transform_motion_decompose(DecompMotionTransform *decomp, const MotionTransform *motion, const Transform *mid);
+void transform_motion_decompose(MotionTransform *decomp, const MotionTransform *motion, const Transform *mid);
 Transform transform_from_viewplane(BoundBox2D& viewplane);
 
 #endif