diff --git a/intern/cycles/blender/blender_camera.cpp b/intern/cycles/blender/blender_camera.cpp index e5214fb5c30..16f555cb58c 100644 --- a/intern/cycles/blender/blender_camera.cpp +++ b/intern/cycles/blender/blender_camera.cpp @@ -67,6 +67,7 @@ struct BlenderCamera { BoundBox2D border; BoundBox2D pano_viewplane; + BoundBox2D viewport_camera_border; Transform matrix; }; @@ -86,6 +87,8 @@ static void blender_camera_init(BlenderCamera *bcam, BL::RenderSettings b_render bcam->border.top = 1.0f; bcam->pano_viewplane.right = 1.0f; bcam->pano_viewplane.top = 1.0f; + bcam->viewport_camera_border.right = 1.0f; + bcam->viewport_camera_border.top = 1.0f; /* render resolution */ bcam->full_width = render_resolution_x(b_render); @@ -365,6 +368,7 @@ static void blender_camera_sync(Camera *cam, BlenderCamera *bcam, int width, int /* border */ cam->border = bcam->border; + cam->viewport_camera_border = bcam->viewport_camera_border; /* set update flag */ if(cam->modified(prevcam)) @@ -516,6 +520,25 @@ static void blender_camera_view_subset(BL::RenderSettings b_render, BL::Scene b_ *cam_box = cam * (1.0f/cam_aspect); } +static void blender_camera_border_subset(BL::RenderSettings b_render, + BL::Scene b_scene, + BL::SpaceView3D b_v3d, + BL::RegionView3D b_rv3d, + BL::Object b_ob, + int width, int height, + const BoundBox2D &border, + BoundBox2D *result) +{ + /* Determine camera viewport subset. */ + BoundBox2D view_box, cam_box; + blender_camera_view_subset(b_render, b_scene, b_ob, b_v3d, b_rv3d, width, height, + &view_box, &cam_box); + + /* Determine viewport subset matching given border. */ + cam_box = cam_box.make_relative_to(view_box); + *result = cam_box.subset(border); +} + static void blender_camera_border(BlenderCamera *bcam, BL::RenderSettings b_render, BL::Scene b_scene, BL::SpaceView3D b_v3d, BL::RegionView3D b_rv3d, int width, int height) { @@ -534,32 +557,45 @@ static void blender_camera_border(BlenderCamera *bcam, BL::RenderSettings b_rend bcam->border.right = b_v3d.render_border_max_x(); bcam->border.bottom = b_v3d.render_border_min_y(); bcam->border.top = b_v3d.render_border_max_y(); - - return; } - } - else if(!b_render.use_border()) return; + } BL::Object b_ob = (b_v3d.lock_camera_and_layers())? b_scene.camera(): b_v3d.camera(); if(!b_ob) return; + /* Determine camera border inside the viewport. */ + BoundBox2D full_border; + blender_camera_border_subset(b_render, + b_scene, + b_v3d, + b_rv3d, + b_ob, + width, height, + full_border, + &bcam->viewport_camera_border); + + if(!b_render.use_border()) { + return; + } + bcam->border.left = b_render.border_min_x(); bcam->border.right = b_render.border_max_x(); bcam->border.bottom = b_render.border_min_y(); bcam->border.top = b_render.border_max_y(); - /* determine camera viewport subset */ - BoundBox2D view_box, cam_box; - - blender_camera_view_subset(b_render, b_scene, b_ob, b_v3d, b_rv3d, width, height, - &view_box, &cam_box); - - /* determine viewport subset matching camera border */ - cam_box = cam_box.make_relative_to(view_box); - bcam->border = cam_box.subset(bcam->border).clamp(); + /* Determine viewport subset matching camera border. */ + blender_camera_border_subset(b_render, + b_scene, + b_v3d, + b_rv3d, + b_ob, + width, height, + bcam->border, + &bcam->border); + bcam->border.clamp(); } void BlenderSync::sync_view(BL::SpaceView3D b_v3d, BL::RegionView3D b_rv3d, int width, int height) diff --git a/intern/cycles/render/camera.cpp b/intern/cycles/render/camera.cpp index 7be3949d138..9d03a9e360e 100644 --- a/intern/cycles/render/camera.cpp +++ b/intern/cycles/render/camera.cpp @@ -109,16 +109,17 @@ void Camera::update() { if(!need_update) return; - + + /* Full viewport to camera border in the viewport. */ + Transform fulltoborder = transform_from_viewplane(viewport_camera_border); + Transform bordertofull = transform_inverse(fulltoborder); + /* ndc to raster */ Transform screentocamera; - Transform ndctoraster = transform_scale(width, height, 1.0f); + Transform ndctoraster = transform_scale(width, height, 1.0f) * bordertofull; /* raster to screen */ - Transform screentondc = - transform_scale(1.0f/(viewplane.right - viewplane.left), - 1.0f/(viewplane.top - viewplane.bottom), 1.0f) * - transform_translate(-viewplane.left, -viewplane.bottom, 0.0f); + Transform screentondc = fulltoborder * transform_from_viewplane(viewplane); Transform screentoraster = ndctoraster * screentondc; Transform rastertoscreen = transform_inverse(screentoraster); @@ -398,5 +399,15 @@ BoundBox Camera::viewplane_bounds_get() return bounds; } -CCL_NAMESPACE_END +Transform Camera::transform_from_viewplane(BoundBox2D &viewplane) +{ + return + transform_scale(1.0f / (viewplane.right - viewplane.left), + 1.0f / (viewplane.top - viewplane.bottom), + 1.0f) * + transform_translate(-viewplane.left, + -viewplane.bottom, + 0.0f); +} +CCL_NAMESPACE_END diff --git a/intern/cycles/render/camera.h b/intern/cycles/render/camera.h index 9525cce8109..1b431e88ac4 100644 --- a/intern/cycles/render/camera.h +++ b/intern/cycles/render/camera.h @@ -76,6 +76,7 @@ public: /* border */ BoundBox2D border; + BoundBox2D viewport_camera_border; /* transformation */ Transform matrix; @@ -123,6 +124,7 @@ public: BoundBox viewplane_bounds_get(); float3 transform_raster_to_world(float raster_x, float raster_y); + Transform transform_from_viewplane(BoundBox2D &viewplane); }; CCL_NAMESPACE_END