Cleanup: Cycles: Restructure camera viewplane calculation
This started with investigating a render issue that appears to be caused by GCC 15. From what I can tell, it was caused by `*viewplane = (*viewplane) * bcam->zoom;`. I'm not entirely sure what the root cause is (potentially pointer aliasing?), but the restructured code works fine now. Pull Request: https://projects.blender.org/blender/blender/pulls/139416
This commit is contained in:
@@ -329,101 +329,63 @@ static Transform blender_camera_matrix(const Transform &tfm,
|
||||
static void blender_camera_viewplane(BlenderCamera *bcam,
|
||||
const int width,
|
||||
const int height,
|
||||
BoundBox2D *viewplane,
|
||||
float *aspectratio,
|
||||
float *sensor_size)
|
||||
BoundBox2D &viewplane,
|
||||
float &aspectratio,
|
||||
float &sensor_size)
|
||||
{
|
||||
/* dimensions */
|
||||
const float xratio = (float)width * bcam->pixelaspect.x;
|
||||
const float yratio = (float)height * bcam->pixelaspect.y;
|
||||
|
||||
/* compute x/y aspect and ratio */
|
||||
float xaspect;
|
||||
float yaspect;
|
||||
float2 aspect;
|
||||
bool horizontal_fit;
|
||||
|
||||
/* sensor fitting */
|
||||
if (bcam->sensor_fit == BlenderCamera::AUTO) {
|
||||
horizontal_fit = (xratio > yratio);
|
||||
if (sensor_size != nullptr) {
|
||||
*sensor_size = bcam->sensor_width;
|
||||
}
|
||||
sensor_size = bcam->sensor_width;
|
||||
}
|
||||
else if (bcam->sensor_fit == BlenderCamera::HORIZONTAL) {
|
||||
horizontal_fit = true;
|
||||
if (sensor_size != nullptr) {
|
||||
*sensor_size = bcam->sensor_width;
|
||||
}
|
||||
sensor_size = bcam->sensor_width;
|
||||
}
|
||||
else {
|
||||
horizontal_fit = false;
|
||||
if (sensor_size != nullptr) {
|
||||
*sensor_size = bcam->sensor_height;
|
||||
}
|
||||
sensor_size = bcam->sensor_height;
|
||||
}
|
||||
|
||||
if (horizontal_fit) {
|
||||
if (aspectratio != nullptr) {
|
||||
*aspectratio = xratio / yratio;
|
||||
}
|
||||
xaspect = *aspectratio;
|
||||
yaspect = 1.0f;
|
||||
aspectratio = xratio / yratio;
|
||||
aspect = make_float2(aspectratio, 1.0f);
|
||||
}
|
||||
else {
|
||||
if (aspectratio != nullptr) {
|
||||
*aspectratio = yratio / xratio;
|
||||
}
|
||||
xaspect = 1.0f;
|
||||
yaspect = *aspectratio;
|
||||
aspectratio = yratio / xratio;
|
||||
aspect = make_float2(1.0f, aspectratio);
|
||||
}
|
||||
|
||||
/* modify aspect for orthographic scale */
|
||||
if (bcam->type == CAMERA_ORTHOGRAPHIC) {
|
||||
xaspect = xaspect * bcam->ortho_scale / (*aspectratio * 2.0f);
|
||||
yaspect = yaspect * bcam->ortho_scale / (*aspectratio * 2.0f);
|
||||
if (aspectratio != nullptr) {
|
||||
*aspectratio = bcam->ortho_scale / 2.0f;
|
||||
}
|
||||
aspect *= bcam->ortho_scale / (aspectratio * 2.0f);
|
||||
aspectratio = bcam->ortho_scale / 2.0f;
|
||||
}
|
||||
|
||||
if (bcam->type == CAMERA_PANORAMA || bcam->type == CAMERA_CUSTOM) {
|
||||
/* Set viewplane for panoramic or custom camera. */
|
||||
if (viewplane != nullptr) {
|
||||
*viewplane = bcam->pano_viewplane;
|
||||
|
||||
/* Modify viewplane for camera shift. */
|
||||
const float shift_factor = (bcam->pano_aspectratio == 0.0f) ?
|
||||
1.0f :
|
||||
*aspectratio / bcam->pano_aspectratio;
|
||||
const float dx = bcam->shift.x * shift_factor;
|
||||
const float dy = bcam->shift.y * shift_factor;
|
||||
|
||||
viewplane->left += dx;
|
||||
viewplane->right += dx;
|
||||
viewplane->bottom += dy;
|
||||
viewplane->top += dy;
|
||||
/* Account for camera shift. */
|
||||
float2 dv = bcam->shift;
|
||||
if (bcam->pano_aspectratio != 0.0f) {
|
||||
dv *= aspectratio / bcam->pano_aspectratio;
|
||||
}
|
||||
|
||||
/* Set viewplane for panoramic or custom camera. */
|
||||
viewplane = bcam->pano_viewplane.offset(dv);
|
||||
}
|
||||
else {
|
||||
/* set viewplane */
|
||||
if (viewplane != nullptr) {
|
||||
viewplane->left = -xaspect;
|
||||
viewplane->right = xaspect;
|
||||
viewplane->bottom = -yaspect;
|
||||
viewplane->top = yaspect;
|
||||
/* Account for camera shift and 3d camera view offset. */
|
||||
const float2 dv = 2.0f * (aspectratio * bcam->shift + bcam->offset * aspect * 2.0f);
|
||||
|
||||
/* zoom for 3d camera view */
|
||||
*viewplane = (*viewplane) * bcam->zoom;
|
||||
|
||||
/* modify viewplane with camera shift and 3d camera view offset */
|
||||
const float dx = 2.0f * (*aspectratio * bcam->shift.x + bcam->offset.x * xaspect * 2.0f);
|
||||
const 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;
|
||||
}
|
||||
/* Set viewplane for perspective or orthographic camera. */
|
||||
viewplane = (BoundBox2D(aspect) * bcam->zoom).offset(dv);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -516,7 +478,7 @@ static void blender_camera_sync(Camera *cam,
|
||||
|
||||
/* viewplane */
|
||||
BoundBox2D viewplane;
|
||||
blender_camera_viewplane(bcam, width, height, &viewplane, &aspectratio, &sensor_size);
|
||||
blender_camera_viewplane(bcam, width, height, viewplane, aspectratio, sensor_size);
|
||||
|
||||
cam->set_viewplane_left(viewplane.left);
|
||||
cam->set_viewplane_right(viewplane.right);
|
||||
@@ -792,9 +754,11 @@ void BlenderSync::sync_camera_motion(BL::RenderSettings &b_render,
|
||||
bcam.pixelaspect.y = b_render.pixel_aspect_y();
|
||||
|
||||
blender_camera_from_object(&bcam, b_engine, b_ob, b_data);
|
||||
|
||||
BoundBox2D viewplane;
|
||||
float aspectratio;
|
||||
float sensor_size;
|
||||
blender_camera_viewplane(&bcam, width, height, nullptr, &aspectratio, &sensor_size);
|
||||
blender_camera_viewplane(&bcam, width, height, viewplane, aspectratio, sensor_size);
|
||||
/* TODO(sergey): De-duplicate calculation with camera sync. */
|
||||
const float fov = 2.0f * atanf((0.5f * sensor_size) / bcam.lens / aspectratio);
|
||||
if (fov != cam->get_fov()) {
|
||||
@@ -825,9 +789,9 @@ static void blender_camera_view_subset(BL::RenderEngine &b_engine,
|
||||
BL::RegionView3D &b_rv3d,
|
||||
const int width,
|
||||
const int height,
|
||||
BoundBox2D *view_box,
|
||||
BoundBox2D *cam_box,
|
||||
float *view_aspect);
|
||||
BoundBox2D &view_box,
|
||||
BoundBox2D &cam_box,
|
||||
float &view_aspect);
|
||||
|
||||
static void blender_camera_from_view(BlenderCamera *bcam,
|
||||
BL::RenderEngine &b_engine,
|
||||
@@ -871,9 +835,9 @@ static void blender_camera_from_view(BlenderCamera *bcam,
|
||||
b_rv3d,
|
||||
width,
|
||||
height,
|
||||
&view_box,
|
||||
&cam_box,
|
||||
&view_aspect);
|
||||
view_box,
|
||||
cam_box,
|
||||
view_aspect);
|
||||
|
||||
bcam->pano_viewplane = view_box.make_relative_to(cam_box);
|
||||
bcam->pano_aspectratio = view_aspect;
|
||||
@@ -926,9 +890,9 @@ static void blender_camera_view_subset(BL::RenderEngine &b_engine,
|
||||
BL::RegionView3D &b_rv3d,
|
||||
const int width,
|
||||
const int height,
|
||||
BoundBox2D *view_box,
|
||||
BoundBox2D *cam_box,
|
||||
float *view_aspect)
|
||||
BoundBox2D &view_box,
|
||||
BoundBox2D &cam_box,
|
||||
float &view_aspect)
|
||||
{
|
||||
BoundBox2D cam;
|
||||
BoundBox2D view;
|
||||
@@ -940,7 +904,7 @@ static void blender_camera_view_subset(BL::RenderEngine &b_engine,
|
||||
blender_camera_from_view(
|
||||
&view_bcam, b_engine, b_scene, b_data, b_v3d, b_rv3d, width, height, true);
|
||||
|
||||
blender_camera_viewplane(&view_bcam, width, height, &view, view_aspect, &sensor_size);
|
||||
blender_camera_viewplane(&view_bcam, width, height, view, view_aspect, sensor_size);
|
||||
|
||||
/* Get camera viewplane. */
|
||||
BlenderCamera cam_bcam(b_render);
|
||||
@@ -951,11 +915,11 @@ static void blender_camera_view_subset(BL::RenderEngine &b_engine,
|
||||
cam_bcam.pixelaspect.y = b_render.pixel_aspect_y();
|
||||
|
||||
blender_camera_viewplane(
|
||||
&cam_bcam, cam_bcam.full_width, cam_bcam.full_height, &cam, &cam_aspect, &sensor_size);
|
||||
&cam_bcam, cam_bcam.full_width, cam_bcam.full_height, cam, cam_aspect, sensor_size);
|
||||
|
||||
/* Return */
|
||||
*view_box = view * (1.0f / *view_aspect);
|
||||
*cam_box = cam * (1.0f / cam_aspect);
|
||||
view_box = view * (1.0f / view_aspect);
|
||||
cam_box = cam * (1.0f / cam_aspect);
|
||||
}
|
||||
|
||||
static void blender_camera_border_subset(BL::RenderEngine &b_engine,
|
||||
@@ -983,9 +947,9 @@ static void blender_camera_border_subset(BL::RenderEngine &b_engine,
|
||||
b_rv3d,
|
||||
width,
|
||||
height,
|
||||
&view_box,
|
||||
&cam_box,
|
||||
&view_aspect);
|
||||
view_box,
|
||||
cam_box,
|
||||
view_aspect);
|
||||
|
||||
/* Determine viewport subset matching given border. */
|
||||
cam_box = cam_box.make_relative_to(view_box);
|
||||
|
||||
@@ -196,24 +196,15 @@ Camera::~Camera() = default;
|
||||
void Camera::compute_auto_viewplane()
|
||||
{
|
||||
if (camera_type == CAMERA_PANORAMA || camera_type == CAMERA_CUSTOM) {
|
||||
viewplane.left = 0.0f;
|
||||
viewplane.right = 1.0f;
|
||||
viewplane.bottom = 0.0f;
|
||||
viewplane.top = 1.0f;
|
||||
viewplane = BoundBox2D();
|
||||
}
|
||||
else {
|
||||
const float aspect = (float)full_width / (float)full_height;
|
||||
if (full_width >= full_height) {
|
||||
viewplane.left = -aspect;
|
||||
viewplane.right = aspect;
|
||||
viewplane.bottom = -1.0f;
|
||||
viewplane.top = 1.0f;
|
||||
viewplane = BoundBox2D(make_float2(aspect, 1.0f));
|
||||
}
|
||||
else {
|
||||
viewplane.left = -1.0f;
|
||||
viewplane.right = 1.0f;
|
||||
viewplane.bottom = -1.0f / aspect;
|
||||
viewplane.top = 1.0f / aspect;
|
||||
viewplane = BoundBox2D(make_float2(1.0f, 1.0f / aspect));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -202,6 +202,11 @@ class BoundBox2D {
|
||||
|
||||
BoundBox2D() = default;
|
||||
|
||||
BoundBox2D(const float2 radius)
|
||||
: left(-radius.x), right(radius.x), bottom(-radius.y), top(radius.y)
|
||||
{
|
||||
}
|
||||
|
||||
bool operator==(const BoundBox2D &other) const
|
||||
{
|
||||
return (left == other.left && right == other.right && bottom == other.bottom &&
|
||||
@@ -265,6 +270,18 @@ class BoundBox2D {
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
BoundBox2D offset(const float2 offset) const
|
||||
{
|
||||
BoundBox2D result;
|
||||
|
||||
result.left = left + offset.x;
|
||||
result.right = right + offset.x;
|
||||
result.bottom = bottom + offset.y;
|
||||
result.top = top + offset.y;
|
||||
|
||||
return result;
|
||||
}
|
||||
};
|
||||
|
||||
CCL_NAMESPACE_END
|
||||
|
||||
Reference in New Issue
Block a user