diff options
-rw-r--r-- | intern/cycles/blender/blender_camera.cpp | 102 | ||||
-rw-r--r-- | intern/cycles/blender/blender_object.cpp | 17 | ||||
-rw-r--r-- | intern/cycles/blender/blender_session.cpp | 28 | ||||
-rw-r--r-- | intern/cycles/blender/blender_sync.cpp | 13 | ||||
-rw-r--r-- | intern/cycles/blender/blender_sync.h | 18 | ||||
-rw-r--r-- | intern/cycles/kernel/kernel_camera.h | 25 | ||||
-rw-r--r-- | intern/cycles/kernel/kernel_types.h | 8 | ||||
-rw-r--r-- | intern/cycles/render/camera.cpp | 24 | ||||
-rw-r--r-- | intern/cycles/render/camera.h | 4 | ||||
-rw-r--r-- | intern/cycles/util/util_transform.h | 5 |
10 files changed, 202 insertions, 42 deletions
diff --git a/intern/cycles/blender/blender_camera.cpp b/intern/cycles/blender/blender_camera.cpp index 90b42ea4ec2..18e9aa8bc17 100644 --- a/intern/cycles/blender/blender_camera.cpp +++ b/intern/cycles/blender/blender_camera.cpp @@ -244,8 +244,11 @@ static Transform blender_camera_matrix(const Transform& tfm, return transform_clear_scale(result); } -static void blender_camera_viewplane(BlenderCamera *bcam, int width, int height, - BoundBox2D *viewplane, float *aspectratio, float *sensor_size) +static void blender_camera_viewplane(BlenderCamera *bcam, + int width, int height, + BoundBox2D *viewplane, + float *aspectratio, + float *sensor_size) { /* dimensions */ float xratio = (float)width*bcam->pixelaspect.x; @@ -258,24 +261,34 @@ static void blender_camera_viewplane(BlenderCamera *bcam, int width, int height, /* sensor fitting */ if(bcam->sensor_fit == BlenderCamera::AUTO) { horizontal_fit = (xratio > yratio); - *sensor_size = bcam->sensor_width; + if(sensor_size != NULL) { + *sensor_size = bcam->sensor_width; + } } else if(bcam->sensor_fit == BlenderCamera::HORIZONTAL) { horizontal_fit = true; - *sensor_size = bcam->sensor_width; + if(sensor_size != NULL) { + *sensor_size = bcam->sensor_width; + } } else { horizontal_fit = false; - *sensor_size = bcam->sensor_height; + if(sensor_size != NULL) { + *sensor_size = bcam->sensor_height; + } } if(horizontal_fit) { - *aspectratio = xratio/yratio; + if(aspectratio != NULL) { + *aspectratio = xratio/yratio; + } xaspect = *aspectratio; yaspect = 1.0f; } else { - *aspectratio = yratio/xratio; + if(aspectratio != NULL) { + *aspectratio = yratio/xratio; + } xaspect = 1.0f; yaspect = *aspectratio; } @@ -284,31 +297,37 @@ static void blender_camera_viewplane(BlenderCamera *bcam, int width, int height, if(bcam->type == CAMERA_ORTHOGRAPHIC) { xaspect = xaspect*bcam->ortho_scale/(*aspectratio*2.0f); yaspect = yaspect*bcam->ortho_scale/(*aspectratio*2.0f); - *aspectratio = bcam->ortho_scale/2.0f; + if(aspectratio != NULL) { + *aspectratio = bcam->ortho_scale/2.0f; + } } if(bcam->type == CAMERA_PANORAMA) { /* set viewplane */ - *viewplane = bcam->pano_viewplane; + if(viewplane != NULL) { + *viewplane = bcam->pano_viewplane; + } } else { /* set viewplane */ - viewplane->left = -xaspect; - viewplane->right = xaspect; - viewplane->bottom = -yaspect; - viewplane->top = yaspect; - - /* zoom for 3d camera view */ - *viewplane = (*viewplane) * bcam->zoom; - - /* modify viewplane with camera shift and 3d camera view offset */ - float dx = 2.0f*(*aspectratio*bcam->shift.x + bcam->offset.x*xaspect*2.0f); - float dy = 2.0f*(*aspectratio*bcam->shift.y + bcam->offset.y*yaspect*2.0f); - - viewplane->left += dx; - viewplane->right += dx; - viewplane->bottom += dy; - viewplane->top += dy; + if(viewplane != NULL) { + viewplane->left = -xaspect; + viewplane->right = xaspect; + viewplane->bottom = -yaspect; + viewplane->top = yaspect; + + /* zoom for 3d camera view */ + *viewplane = (*viewplane) * bcam->zoom; + + /* modify viewplane with camera shift and 3d camera view offset */ + float dx = 2.0f*(*aspectratio*bcam->shift.x + bcam->offset.x*xaspect*2.0f); + float dy = 2.0f*(*aspectratio*bcam->shift.y + bcam->offset.y*yaspect*2.0f); + + viewplane->left += dx; + viewplane->right += dx; + viewplane->bottom += dy; + viewplane->top += dy; + } } } @@ -386,7 +405,10 @@ static void blender_camera_sync(Camera *cam, BlenderCamera *bcam, int width, int cam->motion.pre = cam->matrix; cam->motion.post = cam->matrix; cam->use_motion = false; + cam->use_perspective_motion = false; cam->shuttertime = bcam->shuttertime; + cam->fov_pre = cam->fov; + cam->fov_post = cam->fov; /* border */ cam->border = bcam->border; @@ -435,7 +457,10 @@ void BlenderSync::sync_camera(BL::RenderSettings b_render, BL::Object b_override blender_camera_sync(cam, &bcam, width, height); } -void BlenderSync::sync_camera_motion(BL::Object b_ob, float motion_time) +void BlenderSync::sync_camera_motion(BL::RenderSettings b_render, + BL::Object b_ob, + int width, int height, + float motion_time) { Camera *cam = scene->camera; BL::Array<float, 16> b_ob_matrix; @@ -454,6 +479,31 @@ void BlenderSync::sync_camera_motion(BL::Object b_ob, float motion_time) cam->use_motion = true; } } + + if(cam->type == CAMERA_PERSPECTIVE) { + BlenderCamera bcam; + float aspectratio, sensor_size; + blender_camera_init(&bcam, b_render); + blender_camera_from_object(&bcam, b_engine, b_ob); + blender_camera_viewplane(&bcam, + width, height, + NULL, + &aspectratio, + &sensor_size); + /* TODO(sergey): De-duplicate calculation with camera sync. */ + float fov = 2.0f * atanf((0.5f * sensor_size) / bcam.lens / aspectratio); + if(fov != cam->fov) { + VLOG(1) << "Camera " << b_ob.name() << " FOV change detected."; + if(motion_time == -1.0f) { + cam->fov_pre = fov; + cam->use_perspective_motion = true; + } + else if(motion_time == 1.0f) { + cam->fov_post = fov; + cam->use_perspective_motion = true; + } + } + } } /* Sync 3D View Camera */ diff --git a/intern/cycles/blender/blender_object.cpp b/intern/cycles/blender/blender_object.cpp index 35ba450be41..432c4aaa078 100644 --- a/intern/cycles/blender/blender_object.cpp +++ b/intern/cycles/blender/blender_object.cpp @@ -659,7 +659,11 @@ void BlenderSync::sync_objects(BL::SpaceView3D b_v3d, float motion_time) mesh_motion_synced.clear(); } -void BlenderSync::sync_motion(BL::SpaceView3D b_v3d, BL::Object b_override, void **python_thread_state) +void BlenderSync::sync_motion(BL::RenderSettings b_render, + BL::SpaceView3D b_v3d, + BL::Object b_override, + int width, int height, + void **python_thread_state) { if(scene->need_motion() == Scene::MOTION_NONE) return; @@ -679,6 +683,9 @@ void BlenderSync::sync_motion(BL::SpaceView3D b_v3d, BL::Object b_override, void /* note iteration over motion_times set happens in sorted order */ foreach(float relative_time, motion_times) { + VLOG(1) << "Synchronizing motion for the relative time " + << relative_time << "."; + /* fixed shutter time to get previous and next frame for motion pass */ float shuttertime; @@ -698,8 +705,12 @@ void BlenderSync::sync_motion(BL::SpaceView3D b_v3d, BL::Object b_override, void python_thread_state_save(python_thread_state); /* sync camera, only supports two times at the moment */ - if(relative_time == -1.0f || relative_time == 1.0f) - sync_camera_motion(b_cam, relative_time); + if(relative_time == -1.0f || relative_time == 1.0f) { + sync_camera_motion(b_render, + b_cam, + width, height, + relative_time); + } /* sync object */ sync_objects(b_v3d, relative_time); diff --git a/intern/cycles/blender/blender_session.cpp b/intern/cycles/blender/blender_session.cpp index e1d5e1310d5..8903801d38d 100644 --- a/intern/cycles/blender/blender_session.cpp +++ b/intern/cycles/blender/blender_session.cpp @@ -122,7 +122,12 @@ void BlenderSession::create_session() if(session_pause == false) { /* full data sync */ sync->sync_view(b_v3d, b_rv3d, width, height); - sync->sync_data(b_v3d, b_engine.camera_override(), &python_thread_state); + sync->sync_data(b_render, + b_v3d, + b_engine.camera_override(), + width, height, + &python_thread_state, + b_rlay_name.c_str()); } } else { @@ -477,7 +482,12 @@ void BlenderSession::render() /* update scene */ sync->sync_camera(b_render, b_engine.camera_override(), width, height); - sync->sync_data(b_v3d, b_engine.camera_override(), &python_thread_state, b_rlay_name.c_str()); + sync->sync_data(b_render, + b_v3d, + b_engine.camera_override(), + width, height, + &python_thread_state, + b_rlay_name.c_str()); /* update number of samples per layer */ int samples = sync->get_layer_samples(); @@ -570,7 +580,12 @@ void BlenderSession::bake(BL::Object b_object, const string& pass_type, const in /* update scene */ sync->sync_camera(b_render, b_engine.camera_override(), width, height); - sync->sync_data(b_v3d, b_engine.camera_override(), &python_thread_state); + sync->sync_data(b_render, + b_v3d, + b_engine.camera_override(), + width, height, + &python_thread_state, + b_rlay_name.c_str()); /* get buffer parameters */ SessionParams session_params = BlenderSync::get_session_params(b_engine, b_userpref, b_scene, background); @@ -712,7 +727,12 @@ void BlenderSession::synchronize() } /* data and camera synchronize */ - sync->sync_data(b_v3d, b_engine.camera_override(), &python_thread_state); + sync->sync_data(b_render, + b_v3d, + b_engine.camera_override(), + width, height, + &python_thread_state, + b_rlay_name.c_str()); if(b_rv3d) sync->sync_view(b_v3d, b_rv3d, width, height); diff --git a/intern/cycles/blender/blender_sync.cpp b/intern/cycles/blender/blender_sync.cpp index c5fb7925306..8888d219aac 100644 --- a/intern/cycles/blender/blender_sync.cpp +++ b/intern/cycles/blender/blender_sync.cpp @@ -145,7 +145,12 @@ bool BlenderSync::sync_recalc() return recalc; } -void BlenderSync::sync_data(BL::SpaceView3D b_v3d, BL::Object b_override, void **python_thread_state, const char *layer) +void BlenderSync::sync_data(BL::RenderSettings b_render, + BL::SpaceView3D b_v3d, + BL::Object b_override, + int width, int height, + void **python_thread_state, + const char *layer) { sync_render_layers(b_v3d, layer); sync_integrator(); @@ -157,7 +162,11 @@ void BlenderSync::sync_data(BL::SpaceView3D b_v3d, BL::Object b_override, void * mesh_synced.clear(); /* use for objects and motion sync */ sync_objects(b_v3d); - sync_motion(b_v3d, b_override, python_thread_state); + sync_motion(b_render, + b_v3d, + b_override, + width, height, + python_thread_state); mesh_synced.clear(); } diff --git a/intern/cycles/blender/blender_sync.h b/intern/cycles/blender/blender_sync.h index b8bd14c0f71..efc6ae94542 100644 --- a/intern/cycles/blender/blender_sync.h +++ b/intern/cycles/blender/blender_sync.h @@ -53,7 +53,12 @@ public: /* sync */ bool sync_recalc(); - void sync_data(BL::SpaceView3D b_v3d, BL::Object b_override, void **python_thread_state, const char *layer = 0); + void sync_data(BL::RenderSettings b_render, + BL::SpaceView3D b_v3d, + BL::Object b_override, + int width, int height, + void **python_thread_state, + const char *layer = 0); void sync_render_layers(BL::SpaceView3D b_v3d, const char *layer); void sync_integrator(); void sync_camera(BL::RenderSettings b_render, BL::Object b_override, int width, int height); @@ -75,7 +80,11 @@ private: void sync_lamps(bool update_all); void sync_materials(bool update_all); void sync_objects(BL::SpaceView3D b_v3d, float motion_time = 0.0f); - void sync_motion(BL::SpaceView3D b_v3d, BL::Object b_override, void **python_thread_state); + void sync_motion(BL::RenderSettings b_render, + BL::SpaceView3D b_v3d, + BL::Object b_override, + int width, int height, + void **python_thread_state); void sync_film(); void sync_view(); void sync_world(bool update_all); @@ -98,7 +107,10 @@ private: void sync_light(BL::Object b_parent, int persistent_id[OBJECT_PERSISTENT_ID_SIZE], BL::Object b_ob, Transform& tfm, bool *use_portal); void sync_background_light(bool use_portal); void sync_mesh_motion(BL::Object b_ob, Object *object, float motion_time); - void sync_camera_motion(BL::Object b_ob, float motion_time); + void sync_camera_motion(BL::RenderSettings b_render, + BL::Object b_ob, + int width, int height, + float motion_time); /* particles */ bool sync_dupli_particle(BL::Object b_ob, BL::DupliObject b_dup, Object *object); diff --git a/intern/cycles/kernel/kernel_camera.h b/intern/cycles/kernel/kernel_camera.h index 3ce5134181a..67651f96544 100644 --- a/intern/cycles/kernel/kernel_camera.h +++ b/intern/cycles/kernel/kernel_camera.h @@ -43,7 +43,30 @@ ccl_device void camera_sample_perspective(KernelGlobals *kg, float raster_x, flo { /* create ray form raster position */ Transform rastertocamera = kernel_data.cam.rastertocamera; - float3 Pcamera = transform_perspective(&rastertocamera, make_float3(raster_x, raster_y, 0.0f)); + float3 raster = make_float3(raster_x, raster_y, 0.0f); + float3 Pcamera = transform_perspective(&rastertocamera, raster); + +#ifdef __CAMERA_MOTION__ + if(kernel_data.cam.have_perspective_motion) { + /* TODO(sergey): Currently we interpolate projected coordinate which + * gives nice looking result and which is simple, but is in fact a bit + * different comparing to constructing projective matrix from an + * interpolated field of view. + */ + if(ray->time < 0.5f) { + Transform rastertocamera_pre = kernel_data.cam.perspective_motion.pre; + float3 Pcamera_pre = + transform_perspective(&rastertocamera_pre, raster); + Pcamera = interp(Pcamera_pre, Pcamera, ray->time * 2.0f); + } + else { + Transform rastertocamera_post = kernel_data.cam.perspective_motion.post; + float3 Pcamera_post = + transform_perspective(&rastertocamera_post, raster); + Pcamera = interp(Pcamera, Pcamera_post, (ray->time - 0.5f) * 2.0f); + } + } +#endif ray->P = make_float3(0.0f, 0.0f, 0.0f); ray->D = Pcamera; diff --git a/intern/cycles/kernel/kernel_types.h b/intern/cycles/kernel/kernel_types.h index 46e5d6b2a31..ba8cba1dc83 100644 --- a/intern/cycles/kernel/kernel_types.h +++ b/intern/cycles/kernel/kernel_types.h @@ -778,7 +778,7 @@ typedef struct KernelCamera { /* motion blur */ float shuttertime; - int have_motion; + int have_motion, have_perspective_motion; /* clipping */ float nearclip; @@ -796,7 +796,6 @@ typedef struct KernelCamera { float inv_aperture_ratio; int is_inside_volume; - int pad2; /* more matrices */ Transform screentoworld; @@ -810,6 +809,11 @@ typedef struct KernelCamera { Transform worldtocamera; MotionTransform motion; + + /* Denotes changes in the projective matrix, namely in rastertocamera. + * Used for camera zoom motion blur, + */ + PerspectiveMotionTransform perspective_motion; } KernelCamera; typedef struct KernelFilm { diff --git a/intern/cycles/render/camera.cpp b/intern/cycles/render/camera.cpp index 89505221862..df2a1d348d6 100644 --- a/intern/cycles/render/camera.cpp +++ b/intern/cycles/render/camera.cpp @@ -40,6 +40,7 @@ Camera::Camera() motion.pre = transform_identity(); motion.post = transform_identity(); use_motion = false; + use_perspective_motion = false; aperture_ratio = 1.0f; @@ -170,6 +171,23 @@ void Camera::update() dx = transform_direction(&cameratoworld, dx); dy = transform_direction(&cameratoworld, dy); + /* TODO(sergey): Support other types of camera. */ + if(type == CAMERA_PERSPECTIVE) { + /* TODO(sergey): Move to an utility function and de-duplicate with + * calculation above. + */ + Transform screentocamera_pre = + transform_inverse(transform_perspective(fov_pre, + nearclip, + farclip)); + Transform screentocamera_post = + transform_inverse(transform_perspective(fov_post, + nearclip, + farclip)); + perspective_motion.pre = screentocamera_pre * rastertoscreen; + perspective_motion.post = screentocamera_post * rastertoscreen; + } + need_update = false; need_device_update = true; need_flags_update = true; @@ -205,8 +223,10 @@ void Camera::device_update(Device *device, DeviceScene *dscene, Scene *scene) /* camera motion */ kcam->have_motion = 0; + kcam->have_perspective_motion = 0; if(need_motion == Scene::MOTION_PASS) { + /* TODO(sergey): Support perspective (zoom, fov) motion. */ if(type == CAMERA_PANORAMA) { if(use_motion) { kcam->motion.pre = transform_inverse(motion.pre); @@ -234,6 +254,10 @@ void Camera::device_update(Device *device, DeviceScene *dscene, Scene *scene) transform_motion_decompose((DecompMotionTransform*)&kcam->motion, &motion, &matrix); kcam->have_motion = 1; } + if(use_perspective_motion) { + kcam->perspective_motion = perspective_motion; + kcam->have_perspective_motion = 1; + } } #endif diff --git a/intern/cycles/render/camera.h b/intern/cycles/render/camera.h index 3efbe904e2f..1bedb051112 100644 --- a/intern/cycles/render/camera.h +++ b/intern/cycles/render/camera.h @@ -83,7 +83,9 @@ public: /* motion */ MotionTransform motion; - bool use_motion; + bool use_motion, use_perspective_motion; + float fov_pre, fov_post; + PerspectiveMotionTransform perspective_motion; /* computed camera parameters */ Transform screentoworld; diff --git a/intern/cycles/util/util_transform.h b/intern/cycles/util/util_transform.h index 0b87db0a379..ba8d04b5c16 100644 --- a/intern/cycles/util/util_transform.h +++ b/intern/cycles/util/util_transform.h @@ -55,6 +55,11 @@ typedef struct DecompMotionTransform { float4 post_x, post_y; } DecompMotionTransform; +typedef struct PerspectiveMotionTransform { + Transform pre; + Transform post; +} PerspectiveMotionTransform; + /* Functions */ ccl_device_inline float3 transform_perspective(const Transform *t, const float3 a) |