Fix #136939: Translation is ignored in some nodes
The compositor ignores translation in certain nodes like Corner Pin. Users find this unexpected as adjusting the translation of the input has no effect on the output. The only alternative logical thing to do if translation exists is to clip the image, which this patch do. This affects the following nodes: - File Output. - Map UV (Image input). - Corner Pin. - Plane Track Deform. - Bokeh Blur (Bokeh Kernel input). Pull Request: https://projects.blender.org/blender/blender/pulls/144049
This commit is contained in:
@@ -44,10 +44,14 @@ class RealizeOnDomainOperation : public SimpleOperation {
|
||||
/* Given a potentially transformed domain, compute a domain such that its rotation and scale
|
||||
* become identity and the size of the domain is increased/reduced to adapt to the new
|
||||
* transformation. For instance, if the domain is rotated, the returned domain will have zero
|
||||
* rotation but expanded size to account for the bounding box of the domain after rotation. The
|
||||
* size of the returned domain is bound and clipped by the maximum possible size to avoid
|
||||
* allocations that surpass hardware limits. */
|
||||
static Domain compute_realized_transformation_domain(Context &context, const Domain &domain);
|
||||
* rotation but expanded size to account for the bounding box of the domain after rotation.
|
||||
* Similarly, if the realize_translation argument is true, translation will be set to zero,
|
||||
* though this will not affect the size of the domain in any way. The size of the returned domain
|
||||
* is bound and clipped by the maximum possible size to avoid allocations that surpass hardware
|
||||
* limits. */
|
||||
static Domain compute_realized_transformation_domain(Context &context,
|
||||
const Domain &domain,
|
||||
const bool realize_translation = false);
|
||||
|
||||
protected:
|
||||
/* The operation domain is just the target domain. */
|
||||
|
||||
@@ -207,16 +207,19 @@ Domain RealizeOnDomainOperation::compute_domain()
|
||||
* realization shouldn't be needed. */
|
||||
static constexpr float transformation_tolerance = 10e-6f;
|
||||
|
||||
Domain RealizeOnDomainOperation::compute_realized_transformation_domain(Context &context,
|
||||
const Domain &domain)
|
||||
Domain RealizeOnDomainOperation::compute_realized_transformation_domain(
|
||||
Context &context, const Domain &domain, const bool realize_translation)
|
||||
{
|
||||
const int2 size = domain.size;
|
||||
|
||||
/* If the domain is only infinitesimally rotated or scaled, return a domain with just the
|
||||
* translation component. */
|
||||
* translation component if not realizing translation. */
|
||||
if (math::is_equal(
|
||||
float2x2(domain.transformation), float2x2::identity(), transformation_tolerance))
|
||||
{
|
||||
if (realize_translation) {
|
||||
return Domain(size);
|
||||
}
|
||||
return Domain(size, math::from_location<float3x3>(domain.transformation.location()));
|
||||
}
|
||||
|
||||
@@ -263,7 +266,10 @@ Domain RealizeOnDomainOperation::compute_realized_transformation_domain(Context
|
||||
const int2 safe_size = math::clamp(new_size, int2(1), int2(max_size));
|
||||
|
||||
/* Create a domain from the new safe size and just the translation component of the
|
||||
* transformation, */
|
||||
* transformation if not realizing translation. */
|
||||
if (realize_translation) {
|
||||
return Domain(safe_size);
|
||||
}
|
||||
return Domain(safe_size, math::from_location<float3x3>(domain.transformation.location()));
|
||||
}
|
||||
|
||||
@@ -295,8 +301,11 @@ SimpleOperation *RealizeOnDomainOperation::construct_if_needed(
|
||||
InputRealizationMode::OperationDomain;
|
||||
const Domain target_domain = use_operation_domain ? operation_domain : input_result.domain();
|
||||
|
||||
const bool should_realize_translation = input_descriptor.realization_mode ==
|
||||
InputRealizationMode::Transforms;
|
||||
const Domain realized_target_domain =
|
||||
RealizeOnDomainOperation::compute_realized_transformation_domain(context, target_domain);
|
||||
RealizeOnDomainOperation::compute_realized_transformation_domain(
|
||||
context, target_domain, should_realize_translation);
|
||||
|
||||
/* The input have an almost identical domain to the realized target domain, so no need to realize
|
||||
* it and the operation is not needed. */
|
||||
|
||||
@@ -425,6 +425,15 @@ class CornerPinOperation : public NodeOperation {
|
||||
|
||||
return is_clipped_x || is_clipped_y || output_needed || use_anisotropic;
|
||||
}
|
||||
|
||||
Domain compute_domain() override
|
||||
{
|
||||
Domain domain = this->get_input("Image").domain();
|
||||
/* Reset the location of the domain such that translations take effect, this will result in
|
||||
* clipping but is more expected for the user. */
|
||||
domain.transformation.location() = float2(0.0f);
|
||||
return domain;
|
||||
}
|
||||
};
|
||||
|
||||
static NodeOperation *get_compositor_operation(Context &context, DNode node)
|
||||
|
||||
@@ -1023,6 +1023,19 @@ class FileOutputOperation : public NodeOperation {
|
||||
{
|
||||
return context().get_render_data().scemode & R_MULTIVIEW;
|
||||
}
|
||||
|
||||
Domain compute_domain() override
|
||||
{
|
||||
Domain domain = NodeOperation::compute_domain();
|
||||
if (!this->is_multi_layer()) {
|
||||
return domain;
|
||||
}
|
||||
|
||||
/* Reset the location of the domain in multi-layer case such that translations take effect,
|
||||
* this will result in clipping but is more expected for the user. */
|
||||
domain.transformation.location() = float2(0.0f);
|
||||
return domain;
|
||||
}
|
||||
};
|
||||
|
||||
static NodeOperation *get_compositor_operation(Context &context, DNode node)
|
||||
|
||||
Reference in New Issue
Block a user