This patch implements the pixelate node for the realtime compositor. Differential Revision: https://developer.blender.org/D15662 Reviewed By: Clement Foucault
216 lines
5.0 KiB
C++
216 lines
5.0 KiB
C++
/* SPDX-License-Identifier: GPL-2.0-or-later */
|
|
|
|
#pragma once
|
|
|
|
#include <cmath>
|
|
#include <cstdint>
|
|
|
|
#include "BLI_assert.h"
|
|
#include "BLI_math_base.h"
|
|
#include "BLI_math_matrix.h"
|
|
#include "BLI_math_vec_types.hh"
|
|
#include "BLI_math_vector.h"
|
|
|
|
namespace blender {
|
|
|
|
struct float3x3 {
|
|
/* A 3x3 matrix in column major order. */
|
|
float values[3][3];
|
|
|
|
float3x3() = default;
|
|
|
|
float3x3(const float *matrix)
|
|
{
|
|
memcpy(values, matrix, sizeof(float) * 3 * 3);
|
|
}
|
|
|
|
float3x3(const float matrix[3][3]) : float3x3(static_cast<const float *>(matrix[0]))
|
|
{
|
|
}
|
|
|
|
static float3x3 zero()
|
|
{
|
|
float3x3 result;
|
|
zero_m3(result.values);
|
|
return result;
|
|
}
|
|
|
|
static float3x3 identity()
|
|
{
|
|
float3x3 result;
|
|
unit_m3(result.values);
|
|
return result;
|
|
}
|
|
|
|
static float3x3 from_translation(const float2 translation)
|
|
{
|
|
float3x3 result = identity();
|
|
result.values[2][0] = translation.x;
|
|
result.values[2][1] = translation.y;
|
|
return result;
|
|
}
|
|
|
|
static float3x3 from_rotation(float rotation)
|
|
{
|
|
float3x3 result = zero();
|
|
const float cosine = std::cos(rotation);
|
|
const float sine = std::sin(rotation);
|
|
result.values[0][0] = cosine;
|
|
result.values[0][1] = sine;
|
|
result.values[1][0] = -sine;
|
|
result.values[1][1] = cosine;
|
|
result.values[2][2] = 1.0f;
|
|
return result;
|
|
}
|
|
|
|
static float3x3 from_scale(const float2 scale)
|
|
{
|
|
float3x3 result = zero();
|
|
result.values[0][0] = scale.x;
|
|
result.values[1][1] = scale.y;
|
|
result.values[2][2] = 1.0f;
|
|
return result;
|
|
}
|
|
|
|
static float3x3 from_translation_rotation_scale(const float2 translation,
|
|
float rotation,
|
|
const float2 scale)
|
|
{
|
|
float3x3 result;
|
|
const float cosine = std::cos(rotation);
|
|
const float sine = std::sin(rotation);
|
|
result.values[0][0] = scale.x * cosine;
|
|
result.values[0][1] = scale.x * sine;
|
|
result.values[0][2] = 0.0f;
|
|
result.values[1][0] = scale.y * -sine;
|
|
result.values[1][1] = scale.y * cosine;
|
|
result.values[1][2] = 0.0f;
|
|
result.values[2][0] = translation.x;
|
|
result.values[2][1] = translation.y;
|
|
result.values[2][2] = 1.0f;
|
|
return result;
|
|
}
|
|
|
|
static float3x3 from_normalized_axes(const float2 translation,
|
|
const float2 horizontal,
|
|
const float2 vertical)
|
|
{
|
|
BLI_ASSERT_UNIT_V2(horizontal);
|
|
BLI_ASSERT_UNIT_V2(vertical);
|
|
|
|
float3x3 result;
|
|
result.values[0][0] = horizontal.x;
|
|
result.values[0][1] = horizontal.y;
|
|
result.values[0][2] = 0.0f;
|
|
result.values[1][0] = vertical.x;
|
|
result.values[1][1] = vertical.y;
|
|
result.values[1][2] = 0.0f;
|
|
result.values[2][0] = translation.x;
|
|
result.values[2][1] = translation.y;
|
|
result.values[2][2] = 1.0f;
|
|
return result;
|
|
}
|
|
|
|
/* Construct a transformation that is pivoted around the given origin point. So for instance,
|
|
* from_origin_transformation(from_rotation(M_PI_2), float2(0.0f, 2.0f))
|
|
* will construct a transformation representing a 90 degree rotation around the point (0, 2). */
|
|
static float3x3 from_origin_transformation(const float3x3 &transformation, const float2 origin)
|
|
{
|
|
return from_translation(origin) * transformation * from_translation(-origin);
|
|
}
|
|
|
|
operator float *()
|
|
{
|
|
return &values[0][0];
|
|
}
|
|
|
|
operator const float *() const
|
|
{
|
|
return &values[0][0];
|
|
}
|
|
|
|
float *operator[](const int64_t index)
|
|
{
|
|
BLI_assert(index >= 0);
|
|
BLI_assert(index < 3);
|
|
return &values[index][0];
|
|
}
|
|
|
|
const float *operator[](const int64_t index) const
|
|
{
|
|
BLI_assert(index >= 0);
|
|
BLI_assert(index < 3);
|
|
return &values[index][0];
|
|
}
|
|
|
|
using c_style_float3x3 = float[3][3];
|
|
c_style_float3x3 &ptr()
|
|
{
|
|
return values;
|
|
}
|
|
|
|
const c_style_float3x3 &ptr() const
|
|
{
|
|
return values;
|
|
}
|
|
|
|
friend float3x3 operator*(const float3x3 &a, const float3x3 &b)
|
|
{
|
|
float3x3 result;
|
|
mul_m3_m3m3(result.values, a.values, b.values);
|
|
return result;
|
|
}
|
|
|
|
friend float3 operator*(const float3x3 &a, const float3 &b)
|
|
{
|
|
float3 result;
|
|
mul_v3_m3v3(result, a.values, b);
|
|
return result;
|
|
}
|
|
|
|
void operator*=(const float3x3 &other)
|
|
{
|
|
mul_m3_m3_post(values, other.values);
|
|
}
|
|
|
|
friend float2 operator*(const float3x3 &transformation, const float2 &vector)
|
|
{
|
|
float2 result;
|
|
mul_v2_m3v2(result, transformation.values, vector);
|
|
return result;
|
|
}
|
|
|
|
friend float2 operator*(const float3x3 &transformation, const float (*vector)[2])
|
|
{
|
|
return transformation * float2(vector);
|
|
}
|
|
|
|
float3x3 transposed() const
|
|
{
|
|
float3x3 result;
|
|
transpose_m3_m3(result.values, values);
|
|
return result;
|
|
}
|
|
|
|
float3x3 inverted() const
|
|
{
|
|
float3x3 result;
|
|
invert_m3_m3(result.values, values);
|
|
return result;
|
|
}
|
|
|
|
float2 scale_2d() const
|
|
{
|
|
float2 scale;
|
|
mat3_to_size_2d(scale, values);
|
|
return scale;
|
|
}
|
|
|
|
friend bool operator==(const float3x3 &a, const float3x3 &b)
|
|
{
|
|
return equals_m3m3(a.values, b.values);
|
|
}
|
|
};
|
|
|
|
} // namespace blender
|