diff --git a/intern/cycles/blender/addon/ui.py b/intern/cycles/blender/addon/ui.py index e3076a8ec2c..707f8756f6f 100644 --- a/intern/cycles/blender/addon/ui.py +++ b/intern/cycles/blender/addon/ui.py @@ -809,7 +809,7 @@ class CYCLES_OBJECT_PT_motion_blur(CyclesButtonsPanel, Panel): def poll(cls, context): ob = context.object if CyclesButtonsPanel.poll(context) and ob: - if ob.type in {'MESH', 'CURVE', 'CURVE', 'SURFACE', 'FONT', 'META'}: + if ob.type in {'MESH', 'CURVE', 'CURVE', 'SURFACE', 'FONT', 'META', 'CAMERA'}: return True if ob.dupli_type == 'GROUP' and ob.dupli_group: return True @@ -841,11 +841,9 @@ class CYCLES_OBJECT_PT_motion_blur(CyclesButtonsPanel, Panel): layout.active = (rd.use_motion_blur and cob.use_motion_blur) row = layout.row() - row.prop(cob, "use_deform_motion", text="Deformation") - - sub = row.row() - sub.active = cob.use_deform_motion - sub.prop(cob, "motion_steps", text="Steps") + if ob.type != 'CAMERA': + row.prop(cob, "use_deform_motion", text="Deformation") + row.prop(cob, "motion_steps", text="Steps") class CYCLES_OBJECT_PT_cycles_settings(CyclesButtonsPanel, Panel): diff --git a/intern/cycles/blender/blender_camera.cpp b/intern/cycles/blender/blender_camera.cpp index e5f885c0012..909db8d9449 100644 --- a/intern/cycles/blender/blender_camera.cpp +++ b/intern/cycles/blender/blender_camera.cpp @@ -83,6 +83,8 @@ struct BlenderCamera { Transform matrix; float offscreen_dicing_scale; + + int motion_steps; }; static void blender_camera_init(BlenderCamera *bcam, @@ -226,6 +228,10 @@ static void blender_camera_from_object(BlenderCamera *bcam, bcam->sensor_fit = BlenderCamera::HORIZONTAL; else bcam->sensor_fit = BlenderCamera::VERTICAL; + + if(object_use_motion(b_ob, b_ob)) { + bcam->motion_steps = object_motion_steps(b_ob); + } } else { /* from lamp not implemented yet */ @@ -453,9 +459,7 @@ static void blender_camera_sync(Camera *cam, cam->matrix = blender_camera_matrix(bcam->matrix, bcam->type, bcam->panorama_type); - cam->motion.pre = cam->matrix; - cam->motion.post = cam->matrix; - cam->use_motion = false; + cam->motion.resize(bcam->motion_steps, cam->matrix); cam->use_perspective_motion = false; cam->shuttertime = bcam->shuttertime; cam->fov_pre = cam->fov; @@ -564,20 +568,15 @@ void BlenderSync::sync_camera_motion(BL::RenderSettings& b_render, Transform tfm = get_transform(b_ob_matrix); tfm = blender_camera_matrix(tfm, cam->type, cam->panorama_type); - if(tfm != cam->matrix) { - VLOG(1) << "Camera " << b_ob.name() << " motion detected."; - if(motion_time == 0.0f) { - /* When motion blur is not centered in frame, cam->matrix gets reset. */ - cam->matrix = tfm; - } - else if(motion_time == -1.0f) { - cam->motion.pre = tfm; - cam->use_motion = true; - } - else if(motion_time == 1.0f) { - cam->motion.post = tfm; - cam->use_motion = true; - } + if(motion_time == 0.0f) { + /* When motion blur is not centered in frame, cam->matrix gets reset. */ + cam->matrix = tfm; + } + + /* Set transform in motion array. */ + int motion_step = cam->motion_step(motion_time); + if(motion_step >= 0) { + cam->motion[motion_step] = tfm; } if(cam->type == CAMERA_PERSPECTIVE) { diff --git a/intern/cycles/kernel/geom/geom_object.h b/intern/cycles/kernel/geom/geom_object.h index a7191c50e97..67d039e1bc7 100644 --- a/intern/cycles/kernel/geom/geom_object.h +++ b/intern/cycles/kernel/geom/geom_object.h @@ -82,7 +82,7 @@ ccl_device_inline Transform object_fetch_transform_motion(KernelGlobals *kg, int const ccl_global DecomposedMotionTransform *motion = &kernel_tex_fetch(__objects, object).tfm; Transform tfm; - transform_motion_interpolate(&tfm, motion, time); + transform_motion_array_interpolate(&tfm, &motion->pre, 3, time); return tfm; } diff --git a/intern/cycles/kernel/kernel_camera.h b/intern/cycles/kernel/kernel_camera.h index a0be0ba6454..b73ad47dad3 100644 --- a/intern/cycles/kernel/kernel_camera.h +++ b/intern/cycles/kernel/kernel_camera.h @@ -91,11 +91,12 @@ ccl_device void camera_sample_perspective(KernelGlobals *kg, float raster_x, flo Transform cameratoworld = kernel_data.cam.cameratoworld; #ifdef __CAMERA_MOTION__ - if(kernel_data.cam.have_motion) { - ccl_constant DecomposedMotionTransform *motion = &kernel_data.cam.motion; - transform_motion_interpolate_constant(&cameratoworld, - motion, - ray->time); + if(kernel_data.cam.num_motion_steps) { + transform_motion_array_interpolate( + &cameratoworld, + kernel_tex_array(__camera_motion), + kernel_data.cam.num_motion_steps, + ray->time); } #endif @@ -197,11 +198,12 @@ ccl_device void camera_sample_orthographic(KernelGlobals *kg, float raster_x, fl Transform cameratoworld = kernel_data.cam.cameratoworld; #ifdef __CAMERA_MOTION__ - if(kernel_data.cam.have_motion) { - ccl_constant DecomposedMotionTransform *motion = &kernel_data.cam.motion; - transform_motion_interpolate_constant(&cameratoworld, - motion, - ray->time); + if(kernel_data.cam.num_motion_steps) { + transform_motion_array_interpolate( + &cameratoworld, + kernel_tex_array(__camera_motion), + kernel_data.cam.num_motion_steps, + ray->time); } #endif @@ -227,6 +229,7 @@ ccl_device void camera_sample_orthographic(KernelGlobals *kg, float raster_x, fl /* Panorama Camera */ ccl_device_inline void camera_sample_panorama(ccl_constant KernelCamera *cam, + const ccl_global DecomposedTransform *cam_motion, float raster_x, float raster_y, float lens_u, float lens_v, ccl_addr_space Ray *ray) @@ -269,11 +272,12 @@ ccl_device_inline void camera_sample_panorama(ccl_constant KernelCamera *cam, Transform cameratoworld = cam->cameratoworld; #ifdef __CAMERA_MOTION__ - if(cam->have_motion) { - ccl_constant DecomposedMotionTransform *motion = &cam->motion; - transform_motion_interpolate_constant(&cameratoworld, - motion, - ray->time); + if(cam->num_motion_steps) { + transform_motion_array_interpolate( + &cameratoworld, + cam_motion, + cam->num_motion_steps, + ray->time); } #endif @@ -392,12 +396,16 @@ ccl_device_inline void camera_sample(KernelGlobals *kg, #endif /* sample */ - if(kernel_data.cam.type == CAMERA_PERSPECTIVE) + if(kernel_data.cam.type == CAMERA_PERSPECTIVE) { camera_sample_perspective(kg, raster_x, raster_y, lens_u, lens_v, ray); - else if(kernel_data.cam.type == CAMERA_ORTHOGRAPHIC) + } + else if(kernel_data.cam.type == CAMERA_ORTHOGRAPHIC) { camera_sample_orthographic(kg, raster_x, raster_y, lens_u, lens_v, ray); - else - camera_sample_panorama(&kernel_data.cam, raster_x, raster_y, lens_u, lens_v, ray); + } + else { + const ccl_global DecomposedTransform *cam_motion = kernel_tex_array(__camera_motion); + camera_sample_panorama(&kernel_data.cam, cam_motion, raster_x, raster_y, lens_u, lens_v, ray); + } } /* Utilities */ diff --git a/intern/cycles/kernel/kernel_compat_cpu.h b/intern/cycles/kernel/kernel_compat_cpu.h index 61cd90e9d2a..d26b668cb11 100644 --- a/intern/cycles/kernel/kernel_compat_cpu.h +++ b/intern/cycles/kernel/kernel_compat_cpu.h @@ -118,6 +118,7 @@ template struct texture { #define kernel_tex_fetch_ssef(tex, index) (kg->tex.fetch_ssef(index)) #define kernel_tex_fetch_ssei(tex, index) (kg->tex.fetch_ssei(index)) #define kernel_tex_lookup(tex, t, offset, size) (kg->tex.lookup(t, offset, size)) +#define kernel_tex_array(tex) (kg->tex.data) #define kernel_data (kg->__data) diff --git a/intern/cycles/kernel/kernel_compat_cuda.h b/intern/cycles/kernel/kernel_compat_cuda.h index 9bd7a572f5f..ac63bcf7ac9 100644 --- a/intern/cycles/kernel/kernel_compat_cuda.h +++ b/intern/cycles/kernel/kernel_compat_cuda.h @@ -137,6 +137,7 @@ ccl_device_inline uint ccl_num_groups(uint d) /* Use arrays for regular data. */ #define kernel_tex_fetch(t, index) t[(index)] +#define kernel_tex_array(t) (t) #define kernel_data __data diff --git a/intern/cycles/kernel/kernel_compat_opencl.h b/intern/cycles/kernel/kernel_compat_opencl.h index b02e3bc576d..671c47e2225 100644 --- a/intern/cycles/kernel/kernel_compat_opencl.h +++ b/intern/cycles/kernel/kernel_compat_opencl.h @@ -144,7 +144,8 @@ /* data lookup defines */ #define kernel_data (*kg->data) -#define kernel_tex_fetch(tex, index) ((const ccl_global tex##_t*)(kg->buffers[kg->tex.cl_buffer] + kg->tex.data))[(index)] +#define kernel_tex_array(tex) ((const ccl_global tex##_t*)(kg->buffers[kg->tex.cl_buffer] + kg->tex.data)) +#define kernel_tex_fetch(tex, index) kernel_tex_array(tex)[(index)] /* define NULL */ #define NULL 0 diff --git a/intern/cycles/kernel/kernel_textures.h b/intern/cycles/kernel/kernel_textures.h index 564b3f0f79c..56de5b27605 100644 --- a/intern/cycles/kernel/kernel_textures.h +++ b/intern/cycles/kernel/kernel_textures.h @@ -35,6 +35,9 @@ KERNEL_TEX(KernelObject, __objects) KERNEL_TEX(Transform, __object_motion_pass) KERNEL_TEX(uint, __object_flag) +/* cameras */ +KERNEL_TEX(DecomposedTransform, __camera_motion) + /* triangles */ KERNEL_TEX(uint, __tri_shader) KERNEL_TEX(float4, __tri_vnormal) diff --git a/intern/cycles/kernel/kernel_types.h b/intern/cycles/kernel/kernel_types.h index 6743cc62894..2c3b7ba29a4 100644 --- a/intern/cycles/kernel/kernel_types.h +++ b/intern/cycles/kernel/kernel_types.h @@ -1173,7 +1173,7 @@ typedef struct KernelCamera { /* motion blur */ float shuttertime; - int have_motion, have_perspective_motion; + int num_motion_steps, have_perspective_motion; /* clipping */ float nearclip; @@ -1201,8 +1201,6 @@ typedef struct KernelCamera { ProjectionTransform worldtondc; Transform worldtocamera; - DecomposedMotionTransform motion; - /* Stores changes in the projeciton matrix. Use for camera zoom motion * blur and motion pass output for perspective camera. */ ProjectionTransform perspective_pre; diff --git a/intern/cycles/render/camera.cpp b/intern/cycles/render/camera.cpp index a1c6a279956..38936ffc094 100644 --- a/intern/cycles/render/camera.cpp +++ b/intern/cycles/render/camera.cpp @@ -82,6 +82,7 @@ NODE_DEFINE(Camera) SOCKET_FLOAT(bladesrotation, "Blades Rotation", 0.0f); SOCKET_TRANSFORM(matrix, "Matrix", transform_identity()); + SOCKET_TRANSFORM_ARRAY(motion, "Motion", array()); SOCKET_FLOAT(aperture_ratio, "Aperture Ratio", 1.0f); @@ -151,9 +152,6 @@ Camera::Camera() height = 512; resolution = 1; - motion.pre = transform_identity(); - motion.post = transform_identity(); - use_motion = false; use_perspective_motion = false; shutter_curve.resize(RAMP_TABLE_SIZE); @@ -317,15 +315,22 @@ void Camera::update(Scene *scene) kcam->ndctoworld = ndctoworld; /* camera motion */ - kcam->have_motion = 0; + kcam->num_motion_steps = 0; kcam->have_perspective_motion = 0; + kernel_camera_motion.clear(); + + /* Test if any of the transforms are actually different. */ + bool have_motion = false; + for(size_t i = 0; i < motion.size(); i++) { + have_motion = have_motion || motion[i] != matrix; + } if(need_motion == Scene::MOTION_PASS) { /* TODO(sergey): Support perspective (zoom, fov) motion. */ if(type == CAMERA_PANORAMA) { - if(use_motion) { - kcam->motion_pass_pre = transform_inverse(motion.pre); - kcam->motion_pass_post = transform_inverse(motion.post); + if(have_motion) { + kcam->motion_pass_pre = transform_inverse(motion[0]); + kcam->motion_pass_post = transform_inverse(motion[motion.size()-1]); } else { kcam->motion_pass_pre = kcam->worldtocamera; @@ -333,9 +338,9 @@ void Camera::update(Scene *scene) } } else { - if(use_motion) { - kcam->perspective_pre = cameratoraster * transform_inverse(motion.pre); - kcam->perspective_post = cameratoraster * transform_inverse(motion.post); + if(have_motion) { + kcam->perspective_pre = cameratoraster * transform_inverse(motion[0]); + kcam->perspective_post = cameratoraster * transform_inverse(motion[motion.size()-1]); } else { kcam->perspective_pre = worldtoraster; @@ -344,9 +349,10 @@ void Camera::update(Scene *scene) } } else if(need_motion == Scene::MOTION_BLUR) { - if(use_motion) { - transform_motion_decompose(&kcam->motion, &motion, &matrix); - kcam->have_motion = 1; + if(have_motion) { + kernel_camera_motion.resize(motion.size()); + transform_motion_decompose(kernel_camera_motion.data(), motion.data(), motion.size()); + kcam->num_motion_steps = motion.size(); } /* TODO(sergey): Support other types of camera. */ @@ -469,6 +475,16 @@ void Camera::device_update(Device * /* device */, } dscene->data.cam = kernel_camera; + + size_t num_motion_steps = kernel_camera_motion.size(); + if(num_motion_steps) { + DecomposedTransform *camera_motion = dscene->camera_motion.alloc(num_motion_steps); + memcpy(camera_motion, kernel_camera_motion.data(), sizeof(*camera_motion) * num_motion_steps); + dscene->camera_motion.copy_to_device(); + } + else { + dscene->camera_motion.free(); + } } void Camera::device_update_volume(Device * /*device*/, @@ -495,10 +511,11 @@ void Camera::device_update_volume(Device * /*device*/, } void Camera::device_free(Device * /*device*/, - DeviceScene * /*dscene*/, + DeviceScene *dscene, Scene *scene) { scene->lookup_tables->remove_table(&shutter_table_offset); + dscene->camera_motion.free(); } bool Camera::modified(const Camera& cam) @@ -509,7 +526,6 @@ bool Camera::modified(const Camera& cam) bool Camera::motion_modified(const Camera& cam) { return !((motion == cam.motion) && - (use_motion == cam.use_motion) && (use_perspective_motion == cam.use_perspective_motion)); } @@ -706,17 +722,17 @@ float Camera::world_to_raster_size(float3 P) * may be a better way to do this, but calculating differentials from the * point directly ahead seems to produce good enough results. */ #if 0 - float2 dir = direction_to_panorama(&kernel_camera, normalize(D)); + float2 dir = direction_to_panorama(&kernel_camera, kernel_camera_motion.data(), normalize(D)); float3 raster = transform_perspective(&cameratoraster, make_float3(dir.x, dir.y, 0.0f)); ray.t = 1.0f; - camera_sample_panorama(&kernel_camera, raster.x, raster.y, 0.0f, 0.0f, &ray); + camera_sample_panorama(&kernel_camera, kernel_camera_motion.data(), raster.x, raster.y, 0.0f, 0.0f, &ray); if(ray.t == 0.0f) { /* No differentials, just use from directly ahead. */ - camera_sample_panorama(&kernel_camera, 0.5f*width, 0.5f*height, 0.0f, 0.0f, &ray); + camera_sample_panorama(&kernel_camera, kernel_camera_motion.data(), 0.5f*width, 0.5f*height, 0.0f, 0.0f, &ray); } #else - camera_sample_panorama(&kernel_camera, 0.5f*width, 0.5f*height, 0.0f, 0.0f, &ray); + camera_sample_panorama(&kernel_camera, kernel_camera_motion.data(), 0.5f*width, 0.5f*height, 0.0f, 0.0f, &ray); #endif differential_transfer(&ray.dP, ray.dP, ray.D, ray.dD, ray.D, dist); @@ -728,4 +744,27 @@ float Camera::world_to_raster_size(float3 P) return res; } +bool Camera::use_motion() const +{ + return motion.size() > 1; +} + +float Camera::motion_time(int step) const +{ + return (use_motion()) ? 2.0f * step / (motion.size() - 1) - 1.0f : 0.0f; +} + +int Camera::motion_step(float time) const +{ + if(use_motion()) { + for(int step = 0; step < motion.size(); step++) { + if(time == motion_time(step)) { + return step; + } + } + } + + return -1; +} + CCL_NAMESPACE_END diff --git a/intern/cycles/render/camera.h b/intern/cycles/render/camera.h index 8f49a372f24..37d05c01bd9 100644 --- a/intern/cycles/render/camera.h +++ b/intern/cycles/render/camera.h @@ -141,8 +141,8 @@ public: Transform matrix; /* motion */ - MotionTransform motion; - bool use_motion, use_perspective_motion; + array motion; + bool use_perspective_motion; float fov_pre, fov_post; /* computed camera parameters */ @@ -176,6 +176,7 @@ public: /* Kernel camera data, copied here for dicing. */ KernelCamera kernel_camera; + array kernel_camera_motion; /* functions */ Camera(); @@ -199,6 +200,11 @@ public: /* Calculates the width of a pixel at point in world space. */ float world_to_raster_size(float3 P); + /* Motion blur. */ + float motion_time(int step) const; + int motion_step(float time) const; + bool use_motion() const; + private: /* Private utility functions. */ float3 transform_raster_to_world(float raster_x, float raster_y); diff --git a/intern/cycles/render/object.cpp b/intern/cycles/render/object.cpp index 6201775b992..bde340ae928 100644 --- a/intern/cycles/render/object.cpp +++ b/intern/cycles/render/object.cpp @@ -139,9 +139,10 @@ void Object::compute_bounds(bool motion_blur) if(mtfm.post == transform_empty()) { mtfm.post = tfm; } + mtfm.mid = tfm; DecomposedMotionTransform decomp; - transform_motion_decompose(&decomp, &mtfm, &tfm); + transform_motion_decompose(&decomp.pre, &mtfm.pre, 3); bounds = BoundBox::empty; @@ -151,7 +152,7 @@ void Object::compute_bounds(bool motion_blur) for(float t = 0.0f; t < 1.0f; t += (1.0f/128.0f)) { Transform ttfm; - transform_motion_interpolate(&ttfm, &decomp, t); + transform_motion_array_interpolate(&ttfm, &decomp.pre, 3, t); bounds.grow(mbounds.transformed(&ttfm)); } } @@ -422,8 +423,10 @@ void ObjectManager::device_update_object_transform(UpdateObjectTransformState *s if(ob->use_motion) { /* decompose transformations for interpolation. */ DecomposedMotionTransform decomp; + MotionTransform mtfm = ob->motion; + mtfm.mid = tfm; - transform_motion_decompose(&decomp, &ob->motion, &ob->tfm); + transform_motion_decompose(&decomp.pre, &mtfm.pre, 3); kobject.tfm = decomp; flag |= SD_OBJECT_MOTION; state->have_motion = true; diff --git a/intern/cycles/render/scene.cpp b/intern/cycles/render/scene.cpp index e9b9b417e30..6fc6e453aff 100644 --- a/intern/cycles/render/scene.cpp +++ b/intern/cycles/render/scene.cpp @@ -62,6 +62,7 @@ DeviceScene::DeviceScene(Device *device) objects(device, "__objects", MEM_TEXTURE), object_motion_pass(device, "__object_motion_pass", MEM_TEXTURE), object_flag(device, "__object_flag", MEM_TEXTURE), + camera_motion(device, "__camera_motion", MEM_TEXTURE), attributes_map(device, "__attributes_map", MEM_TEXTURE), attributes_float(device, "__attributes_float", MEM_TEXTURE), attributes_float3(device, "__attributes_float3", MEM_TEXTURE), diff --git a/intern/cycles/render/scene.h b/intern/cycles/render/scene.h index aebd84f92d8..74e1df2f1d2 100644 --- a/intern/cycles/render/scene.h +++ b/intern/cycles/render/scene.h @@ -90,6 +90,9 @@ public: device_vector object_motion_pass; device_vector object_flag; + /* cameras */ + device_vector camera_motion; + /* attributes */ device_vector attributes_map; device_vector attributes_float; diff --git a/intern/cycles/render/session.cpp b/intern/cycles/render/session.cpp index e8d9558c38d..5732faf2a36 100644 --- a/intern/cycles/render/session.cpp +++ b/intern/cycles/render/session.cpp @@ -656,7 +656,7 @@ DeviceRequestedFeatures Session::get_requested_device_features() */ requested_features.use_hair = false; requested_features.use_object_motion = false; - requested_features.use_camera_motion = scene->camera->use_motion; + requested_features.use_camera_motion = scene->camera->use_motion(); foreach(Object *object, scene->objects) { Mesh *mesh = object->mesh; if(mesh->num_curves()) { diff --git a/intern/cycles/util/util_transform.cpp b/intern/cycles/util/util_transform.cpp index e4e0d627497..206c3da23eb 100644 --- a/intern/cycles/util/util_transform.cpp +++ b/intern/cycles/util/util_transform.cpp @@ -261,18 +261,18 @@ static void transform_decompose(DecomposedTransform *decomp, const Transform *tf decomp->w = make_float4(scale.y.z, scale.z.x, scale.z.y, scale.z.z); } -void transform_motion_decompose(DecomposedMotionTransform *decomp, const MotionTransform *motion, const Transform *mid) +void transform_motion_decompose(DecomposedTransform *decomp, const Transform *motion, size_t size) { - transform_decompose(&decomp->pre, &motion->pre); - transform_decompose(&decomp->mid, mid); - transform_decompose(&decomp->post, &motion->post); + for(size_t i = 0; i < size; i++) { + transform_decompose(decomp + i, motion + i); - /* 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->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(i > 0) { + /* 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[i-1].x, decomp[i].x) < 0.0f) + decomp[i-1].x = -decomp[i-1].x; + } + } } Transform transform_from_viewplane(BoundBox2D& viewplane) diff --git a/intern/cycles/util/util_transform.h b/intern/cycles/util/util_transform.h index 12f8405f233..ade74364876 100644 --- a/intern/cycles/util/util_transform.h +++ b/intern/cycles/util/util_transform.h @@ -409,58 +409,28 @@ ccl_device_inline void transform_compose(Transform *tfm, const DecomposedTransfo tfm->z = make_float4(dot(rotation_z, scale_x), dot(rotation_z, scale_y), dot(rotation_z, scale_z), decomp->y.z); } -ccl_device void transform_motion_interpolate(Transform *tfm, const ccl_global DecomposedMotionTransform *motion, float t) +/* Interpolate from array of decomposed transforms. */ +ccl_device void transform_motion_array_interpolate(Transform *tfm, + const ccl_global DecomposedTransform *motion, + uint numsteps, + float time) { + /* Figure out which steps we need to interpolate. */ + int maxstep = numsteps-1; + int step = min((int)(time*maxstep), maxstep-1); + float t = time*maxstep - step; + + const ccl_global DecomposedTransform *a = motion + step; + const ccl_global DecomposedTransform *b = motion + step + 1; + + /* Interpolate rotation, translation and scale. */ DecomposedTransform decomp; + decomp.x = quat_interpolate(a->x, b->x, t); + decomp.y = (1.0f - t)*a->y + t*b->y; + decomp.z = (1.0f - t)*a->z + t*b->z; + decomp.w = (1.0f - t)*a->w + t*b->w; - /* 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 = (1.0f - t)*motion->pre.y + t*motion->mid.y; - 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 = (1.0f - t)*motion->mid.y + t*motion->post.y; - 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); -} - -ccl_device void transform_motion_interpolate_constant(Transform *tfm, ccl_constant DecomposedMotionTransform *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? */ - DecomposedTransform decomp; - - /* 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 = (1.0f - t)*motion->pre.y + t*motion->mid.y; - 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 = (1.0f - t)*motion->mid.y + t*motion->post.y; - 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 */ + /* Compose rotation, translation, scale into matrix. */ transform_compose(tfm, &decomp); } @@ -479,7 +449,7 @@ ccl_device_inline bool operator==(const MotionTransform& A, const MotionTransfor } float4 transform_to_quat(const Transform& tfm); -void transform_motion_decompose(DecomposedMotionTransform *decomp, const MotionTransform *motion, const Transform *mid); +void transform_motion_decompose(DecomposedTransform *decomp, const Transform *motion, size_t size); Transform transform_from_viewplane(BoundBox2D& viewplane); #endif diff --git a/intern/cycles/util/util_vector.h b/intern/cycles/util/util_vector.h index 625c19c7c46..e98e4e34181 100644 --- a/intern/cycles/util/util_vector.h +++ b/intern/cycles/util/util_vector.h @@ -215,6 +215,18 @@ public: return data_; } + T* resize(size_t newsize, const T& value) + { + size_t oldsize = size(); + resize(newsize); + + for(size_t i = oldsize; i < size(); i++) { + data_[i] = value; + } + + return data_; + } + void clear() { if(data_ != NULL) {