Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
path: root/source
diff options
context:
space:
mode:
authorManuel Castilla <manzanillawork@gmail.com>2021-08-03 22:01:40 +0300
committerManuel Castilla <manzanillawork@gmail.com>2021-08-03 22:01:40 +0300
commit79ffaa48165a2df23f01964de2eeeca0ea56bdb8 (patch)
treecadd8d30fb2132f2cacf2d8b2601e96c2e404ace /source
parentb02069ef4da254814e4c35a260349885dea797d3 (diff)
Compositor: Full frame Plane Track Deform and Corner Pin nodes
Diffstat (limited to 'source')
-rw-r--r--source/blender/compositor/operations/COM_PlaneCornerPinOperation.cc78
-rw-r--r--source/blender/compositor/operations/COM_PlaneCornerPinOperation.h3
-rw-r--r--source/blender/compositor/operations/COM_PlaneDistortCommonOperation.cc105
-rw-r--r--source/blender/compositor/operations/COM_PlaneDistortCommonOperation.h16
4 files changed, 198 insertions, 4 deletions
diff --git a/source/blender/compositor/operations/COM_PlaneCornerPinOperation.cc b/source/blender/compositor/operations/COM_PlaneCornerPinOperation.cc
index 3577860b93d..fcbf42c8713 100644
--- a/source/blender/compositor/operations/COM_PlaneCornerPinOperation.cc
+++ b/source/blender/compositor/operations/COM_PlaneCornerPinOperation.cc
@@ -16,6 +16,7 @@
*/
#include "COM_PlaneCornerPinOperation.h"
+#include "COM_ConstantOperation.h"
#include "COM_ReadBufferOperation.h"
#include "MEM_guardedalloc.h"
@@ -28,6 +29,11 @@
namespace blender::compositor {
+constexpr int LOWER_LEFT_CORNER_INDEX = 0;
+constexpr int LOWER_RIGHT_CORNER_INDEX = 1;
+constexpr int UPPER_RIGHT_CORNER_INDEX = 2;
+constexpr int UPPER_LEFT_CORNER_INDEX = 3;
+
static bool check_corners(float corners[4][2])
{
int i, next, prev;
@@ -58,6 +64,7 @@ static bool check_corners(float corners[4][2])
return true;
}
+/* TODO(manzanilla): to be removed with tiled implementation. */
static void readCornersFromSockets(rcti *rect, SocketReader *readers[4], float corners[4][2])
{
for (int i = 0; i < 4; i++) {
@@ -87,6 +94,53 @@ static void readCornersFromSockets(rcti *rect, SocketReader *readers[4], float c
}
}
+static void set_default_corner(const int corner_idx, float corner[2])
+{
+ BLI_assert(corner_idx >= 0 && corner_idx < 4);
+ switch (corner_idx) {
+ case LOWER_LEFT_CORNER_INDEX:
+ corner[0] = 0.0f;
+ corner[1] = 0.0f;
+ break;
+ case LOWER_RIGHT_CORNER_INDEX:
+ corner[0] = 1.0f;
+ corner[1] = 0.0f;
+ break;
+ case UPPER_RIGHT_CORNER_INDEX:
+ corner[0] = 1.0f;
+ corner[1] = 1.0f;
+ break;
+ case UPPER_LEFT_CORNER_INDEX:
+ corner[0] = 0.0f;
+ corner[1] = 1.0f;
+ break;
+ }
+}
+
+static void read_input_corners(NodeOperation *op, const int first_input_idx, float r_corners[4][2])
+{
+ for (const int i : IndexRange(4)) {
+ NodeOperation *input = op->get_input_operation(i + first_input_idx);
+ if (input->get_flags().is_constant_operation) {
+ ConstantOperation *corner_input = static_cast<ConstantOperation *>(input);
+ copy_v2_v2(r_corners[i], corner_input->get_constant_elem());
+ }
+ else {
+ set_default_corner(i, r_corners[i]);
+ }
+ }
+
+ /* Convexity check: concave corners need to be prevented, otherwise
+ * #BKE_tracking_homography_between_two_quads will freeze. */
+ if (!check_corners(r_corners)) {
+ /* Revert to default corners. There could be a more elegant solution,
+ * this prevents freezing at least. */
+ for (const int i : IndexRange(4)) {
+ set_default_corner(i, r_corners[i]);
+ }
+ }
+}
+
/* ******** PlaneCornerPinMaskOperation ******** */
PlaneCornerPinMaskOperation::PlaneCornerPinMaskOperation() : m_corners_ready(false)
@@ -103,6 +157,17 @@ PlaneCornerPinMaskOperation::PlaneCornerPinMaskOperation() : m_corners_ready(fal
flags.complex = true;
}
+void PlaneCornerPinMaskOperation::init_data()
+{
+ if (execution_model_ == eExecutionModel::FullFrame) {
+ float corners[4][2];
+ read_input_corners(this, 0, corners);
+ calculateCorners(corners, true, 0);
+ }
+}
+
+/* TODO(manzanilla): to be removed with tiled implementation. Same for #deinitExecution and do the
+ * same on #PlaneCornerPinWarpImageOperation. */
void PlaneCornerPinMaskOperation::initExecution()
{
PlaneDistortMaskOperation::initExecution();
@@ -147,6 +212,10 @@ void *PlaneCornerPinMaskOperation::initializeTileData(rcti *rect)
void PlaneCornerPinMaskOperation::determineResolution(unsigned int resolution[2],
unsigned int preferredResolution[2])
{
+ if (execution_model_ == eExecutionModel::FullFrame) {
+ /* Determine inputs resolution. */
+ PlaneDistortMaskOperation::determineResolution(resolution, preferredResolution);
+ }
resolution[0] = preferredResolution[0];
resolution[1] = preferredResolution[1];
}
@@ -161,6 +230,15 @@ PlaneCornerPinWarpImageOperation::PlaneCornerPinWarpImageOperation() : m_corners
addInputSocket(DataType::Vector);
}
+void PlaneCornerPinWarpImageOperation::init_data()
+{
+ if (execution_model_ == eExecutionModel::FullFrame) {
+ float corners[4][2];
+ read_input_corners(this, 1, corners);
+ calculateCorners(corners, true, 0);
+ }
+}
+
void PlaneCornerPinWarpImageOperation::initExecution()
{
PlaneDistortWarpImageOperation::initExecution();
diff --git a/source/blender/compositor/operations/COM_PlaneCornerPinOperation.h b/source/blender/compositor/operations/COM_PlaneCornerPinOperation.h
index 91c0cd9e16b..7d857d270a0 100644
--- a/source/blender/compositor/operations/COM_PlaneCornerPinOperation.h
+++ b/source/blender/compositor/operations/COM_PlaneCornerPinOperation.h
@@ -31,11 +31,13 @@ namespace blender::compositor {
class PlaneCornerPinMaskOperation : public PlaneDistortMaskOperation {
private:
+ /* TODO(manzanilla): to be removed with tiled implementation. */
bool m_corners_ready;
public:
PlaneCornerPinMaskOperation();
+ void init_data() override;
void initExecution() override;
void deinitExecution() override;
@@ -52,6 +54,7 @@ class PlaneCornerPinWarpImageOperation : public PlaneDistortWarpImageOperation {
public:
PlaneCornerPinWarpImageOperation();
+ void init_data() override;
void initExecution() override;
void deinitExecution() override;
diff --git a/source/blender/compositor/operations/COM_PlaneDistortCommonOperation.cc b/source/blender/compositor/operations/COM_PlaneDistortCommonOperation.cc
index 4edcc206f5b..91af4f0e5aa 100644
--- a/source/blender/compositor/operations/COM_PlaneDistortCommonOperation.cc
+++ b/source/blender/compositor/operations/COM_PlaneDistortCommonOperation.cc
@@ -85,8 +85,9 @@ void PlaneDistortWarpImageOperation::calculateCorners(const float corners[4][2],
{
PlaneDistortBaseOperation::calculateCorners(corners, normalized, sample);
- const int width = this->m_pixelReader->getWidth();
- const int height = this->m_pixelReader->getHeight();
+ const NodeOperation *image = get_input_operation(0);
+ const int width = image->getWidth();
+ const int height = image->getHeight();
float frame_corners[4][2] = {
{0.0f, 0.0f}, {(float)width, 0.0f}, {(float)width, (float)height}, {0.0f, (float)height}};
MotionSample *sample_data = &this->m_samples[sample];
@@ -127,6 +128,34 @@ void PlaneDistortWarpImageOperation::executePixelSampled(float output[4],
}
}
+void PlaneDistortWarpImageOperation::update_memory_buffer_partial(MemoryBuffer *output,
+ const rcti &area,
+ Span<MemoryBuffer *> inputs)
+{
+ const MemoryBuffer *input_img = inputs[0];
+ float uv[2];
+ float deriv[2][2];
+ BuffersIterator<float> it = output->iterate_with({}, area);
+ if (this->m_motion_blur_samples == 1) {
+ for (; !it.is_end(); ++it) {
+ warpCoord(it.x, it.y, this->m_samples[0].perspectiveMatrix, uv, deriv);
+ input_img->read_elem_filtered(uv[0], uv[1], deriv[0], deriv[1], it.out);
+ }
+ }
+ else {
+ for (; !it.is_end(); ++it) {
+ zero_v4(it.out);
+ for (const int sample : IndexRange(this->m_motion_blur_samples)) {
+ float color[4];
+ warpCoord(it.x, it.y, this->m_samples[sample].perspectiveMatrix, uv, deriv);
+ input_img->read_elem_filtered(uv[0], uv[1], deriv[0], deriv[1], color);
+ add_v4_v4(it.out, color);
+ }
+ mul_v4_fl(it.out, 1.0f / (float)this->m_motion_blur_samples);
+ }
+ }
+}
+
bool PlaneDistortWarpImageOperation::determineDependingAreaOfInterest(
rcti *input, ReadBufferOperation *readOperation, rcti *output)
{
@@ -157,6 +186,41 @@ bool PlaneDistortWarpImageOperation::determineDependingAreaOfInterest(
return NodeOperation::determineDependingAreaOfInterest(&newInput, readOperation, output);
}
+void PlaneDistortWarpImageOperation::get_area_of_interest(const int input_idx,
+ const rcti &output_area,
+ rcti &r_input_area)
+{
+ if (input_idx != 0) {
+ r_input_area = output_area;
+ return;
+ }
+
+ float min[2], max[2];
+ INIT_MINMAX2(min, max);
+ for (int sample = 0; sample < this->m_motion_blur_samples; sample++) {
+ float UVs[4][2];
+ float deriv[2][2];
+ MotionSample *sample_data = &this->m_samples[sample];
+ /* TODO(sergey): figure out proper way to do this. */
+ warpCoord(
+ output_area.xmin - 2, output_area.ymin - 2, sample_data->perspectiveMatrix, UVs[0], deriv);
+ warpCoord(
+ output_area.xmax + 2, output_area.ymin - 2, sample_data->perspectiveMatrix, UVs[1], deriv);
+ warpCoord(
+ output_area.xmax + 2, output_area.ymax + 2, sample_data->perspectiveMatrix, UVs[2], deriv);
+ warpCoord(
+ output_area.xmin - 2, output_area.ymax + 2, sample_data->perspectiveMatrix, UVs[3], deriv);
+ for (int i = 0; i < 4; i++) {
+ minmax_v2v2_v2(min, max, UVs[i]);
+ }
+ }
+
+ r_input_area.xmin = min[0] - 1;
+ r_input_area.ymin = min[1] - 1;
+ r_input_area.xmax = max[0] + 1;
+ r_input_area.ymax = max[1] + 1;
+}
+
/* ******** PlaneDistort Mask ******** */
PlaneDistortMaskOperation::PlaneDistortMaskOperation() : PlaneDistortBaseOperation()
@@ -219,4 +283,41 @@ void PlaneDistortMaskOperation::executePixelSampled(float output[4],
}
}
+void PlaneDistortMaskOperation::update_memory_buffer_partial(MemoryBuffer *output,
+ const rcti &area,
+ Span<MemoryBuffer *> UNUSED(inputs))
+{
+ for (BuffersIterator<float> it = output->iterate_with({}, area); !it.is_end(); ++it) {
+ int inside_count = 0;
+ for (const int motion_sample : IndexRange(this->m_motion_blur_samples)) {
+ MotionSample &sample = this->m_samples[motion_sample];
+ inside_count += get_jitter_samples_inside_count(it.x, it.y, sample);
+ }
+ *it.out = (float)inside_count / (this->m_osa * this->m_motion_blur_samples);
+ }
+}
+
+int PlaneDistortMaskOperation::get_jitter_samples_inside_count(int x,
+ int y,
+ MotionSample &sample_data)
+{
+ float point[2];
+ int inside_count = 0;
+ for (int sample = 0; sample < this->m_osa; sample++) {
+ point[0] = x + this->m_jitter[sample][0];
+ point[1] = y + this->m_jitter[sample][1];
+ if (isect_point_tri_v2(point,
+ sample_data.frameSpaceCorners[0],
+ sample_data.frameSpaceCorners[1],
+ sample_data.frameSpaceCorners[2]) ||
+ isect_point_tri_v2(point,
+ sample_data.frameSpaceCorners[0],
+ sample_data.frameSpaceCorners[2],
+ sample_data.frameSpaceCorners[3])) {
+ inside_count++;
+ }
+ }
+ return inside_count;
+}
+
} // namespace blender::compositor
diff --git a/source/blender/compositor/operations/COM_PlaneDistortCommonOperation.h b/source/blender/compositor/operations/COM_PlaneDistortCommonOperation.h
index cc6e4d00d71..3ef9c1dfab8 100644
--- a/source/blender/compositor/operations/COM_PlaneDistortCommonOperation.h
+++ b/source/blender/compositor/operations/COM_PlaneDistortCommonOperation.h
@@ -20,7 +20,7 @@
#include <string.h>
-#include "COM_NodeOperation.h"
+#include "COM_MultiThreadedOperation.h"
#include "DNA_movieclip_types.h"
#include "DNA_tracking_types.h"
@@ -32,7 +32,7 @@ namespace blender::compositor {
#define PLANE_DISTORT_MAX_SAMPLES 64
-class PlaneDistortBaseOperation : public NodeOperation {
+class PlaneDistortBaseOperation : public MultiThreadedOperation {
protected:
struct MotionSample {
float frameSpaceCorners[4][2]; /* Corners coordinates in pixel space. */
@@ -78,6 +78,11 @@ class PlaneDistortWarpImageOperation : public PlaneDistortBaseOperation {
bool determineDependingAreaOfInterest(rcti *input,
ReadBufferOperation *readOperation,
rcti *output) override;
+
+ void get_area_of_interest(int input_idx, const rcti &output_area, rcti &r_input_area) override;
+ void update_memory_buffer_partial(MemoryBuffer *output,
+ const rcti &area,
+ Span<MemoryBuffer *> inputs) override;
};
class PlaneDistortMaskOperation : public PlaneDistortBaseOperation {
@@ -91,6 +96,13 @@ class PlaneDistortMaskOperation : public PlaneDistortBaseOperation {
void initExecution() override;
void executePixelSampled(float output[4], float x, float y, PixelSampler sampler) override;
+
+ void update_memory_buffer_partial(MemoryBuffer *output,
+ const rcti &area,
+ Span<MemoryBuffer *> inputs) override;
+
+ private:
+ int get_jitter_samples_inside_count(int x, int y, MotionSample &sample_data);
};
} // namespace blender::compositor