diff options
20 files changed, 657 insertions, 157 deletions
diff --git a/release/scripts/startup/nodeitems_builtins.py b/release/scripts/startup/nodeitems_builtins.py index 6ade4911215..be989f0aee7 100644 --- a/release/scripts/startup/nodeitems_builtins.py +++ b/release/scripts/startup/nodeitems_builtins.py @@ -349,6 +349,7 @@ compositor_node_categories = [ NodeItem("CompositorNodeTransform"), NodeItem("CompositorNodeStabilize"), NodeItem("CompositorNodePlaneTrackDeform"), + NodeItem("CompositorNodeCornerPin"), ]), CompositorNodeCategory("CMP_GROUP", "Group", items=node_group_items), CompositorNodeCategory("CMP_LAYOUT", "Layout", items=[ diff --git a/source/blender/blenkernel/BKE_node.h b/source/blender/blenkernel/BKE_node.h index 59ea921e11e..af912b998c4 100644 --- a/source/blender/blenkernel/BKE_node.h +++ b/source/blender/blenkernel/BKE_node.h @@ -897,6 +897,7 @@ void ntreeGPUMaterialNodes(struct bNodeTree *ntree, struct GPUMateria #define CMP_NODE_MAP_RANGE 319 #define CMP_NODE_PLANETRACKDEFORM 320 +#define CMP_NODE_CORNERPIN 321 /* channel toggles */ #define CMP_CHAN_RGB 1 diff --git a/source/blender/blenkernel/intern/node.c b/source/blender/blenkernel/intern/node.c index d6225560e32..249fb5264fe 100644 --- a/source/blender/blenkernel/intern/node.c +++ b/source/blender/blenkernel/intern/node.c @@ -3460,6 +3460,7 @@ static void registerCompositNodes(void) register_node_type_cmp_mask(); register_node_type_cmp_trackpos(); register_node_type_cmp_planetrackdeform(); + register_node_type_cmp_cornerpin(); } static void registerShaderNodes(void) diff --git a/source/blender/compositor/CMakeLists.txt b/source/blender/compositor/CMakeLists.txt index 11add975db5..cbb1017facd 100644 --- a/source/blender/compositor/CMakeLists.txt +++ b/source/blender/compositor/CMakeLists.txt @@ -185,6 +185,8 @@ set(SRC nodes/COM_GlareNode.cpp nodes/COM_GlareNode.h + nodes/COM_CornerPinNode.cpp + nodes/COM_CornerPinNode.h nodes/COM_PlaneTrackDeformNode.cpp nodes/COM_PlaneTrackDeformNode.h @@ -488,12 +490,12 @@ set(SRC operations/COM_ProjectorLensDistortionOperation.h operations/COM_ScreenLensDistortionOperation.cpp operations/COM_ScreenLensDistortionOperation.h - operations/COM_PlaneTrackCommonOperation.cpp - operations/COM_PlaneTrackCommonOperation.h - operations/COM_PlaneTrackMaskOperation.cpp - operations/COM_PlaneTrackMaskOperation.h - operations/COM_PlaneTrackWarpImageOperation.cpp - operations/COM_PlaneTrackWarpImageOperation.h + operations/COM_PlaneDistortCommonOperation.cpp + operations/COM_PlaneDistortCommonOperation.h + operations/COM_PlaneTrackOperation.cpp + operations/COM_PlaneTrackOperation.h + operations/COM_PlaneCornerPinOperation.cpp + operations/COM_PlaneCornerPinOperation.h #Filter operations operations/COM_ConvolutionFilterOperation.h diff --git a/source/blender/compositor/intern/COM_Converter.cpp b/source/blender/compositor/intern/COM_Converter.cpp index 384cfbe47fa..7103b49f32f 100644 --- a/source/blender/compositor/intern/COM_Converter.cpp +++ b/source/blender/compositor/intern/COM_Converter.cpp @@ -49,6 +49,7 @@ #include "COM_ConvertAlphaNode.h" #include "COM_ConvertOperation.h" #include "COM_Converter.h" +#include "COM_CornerPinNode.h" #include "COM_CropNode.h" #include "COM_DefocusNode.h" #include "COM_DespeckleNode.h" @@ -401,6 +402,9 @@ Node *Converter::convert(bNode *b_node, bool fast) case CMP_NODE_PLANETRACKDEFORM: node = new PlaneTrackDeformNode(b_node); break; + case CMP_NODE_CORNERPIN: + node = new CornerPinNode(b_node); + break; default: node = new MuteNode(b_node); break; diff --git a/source/blender/compositor/nodes/COM_CornerPinNode.cpp b/source/blender/compositor/nodes/COM_CornerPinNode.cpp new file mode 100644 index 00000000000..3115be8b178 --- /dev/null +++ b/source/blender/compositor/nodes/COM_CornerPinNode.cpp @@ -0,0 +1,67 @@ +/* + * Copyright 2014, Blender Foundation. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * Contributor: + * Lukas Toenne + */ + +#include "COM_CornerPinNode.h" +#include "COM_ExecutionSystem.h" + +#include "COM_PlaneCornerPinOperation.h" + +CornerPinNode::CornerPinNode(bNode *editorNode) : Node(editorNode) +{ +} + +void CornerPinNode::convertToOperations(ExecutionSystem *graph, CompositorContext *context) +{ + InputSocket *input_image = this->getInputSocket(0); + /* note: socket order differs between UI node and operations: + * bNode uses intuitive order following top-down layout: + * upper-left, upper-right, lower-left, lower-right + * Operations use same order as the tracking blenkernel functions expect: + * lower-left, lower-right, upper-right, upper-left + */ + const int node_corner_index[4] = { 3, 4, 2, 1 }; + + OutputSocket *output_warped_image = this->getOutputSocket(0); + OutputSocket *output_plane = this->getOutputSocket(1); + + PlaneCornerPinWarpImageOperation *warp_image_operation = new PlaneCornerPinWarpImageOperation(); + + input_image->relinkConnections(warp_image_operation->getInputSocket(0), 0, graph); + for (int i = 0; i < 4; ++i) { + int node_index = node_corner_index[i]; + getInputSocket(node_index)->relinkConnections(warp_image_operation->getInputSocket(i+1), + node_index, graph); + } + output_warped_image->relinkConnections(warp_image_operation->getOutputSocket()); + + graph->addOperation(warp_image_operation); + + PlaneCornerPinMaskOperation *plane_mask_operation = new PlaneCornerPinMaskOperation(); + + /* connect mask op inputs to the same sockets as the warp image op */ + for (int i = 0; i < 4; ++i) + addLink(graph, + warp_image_operation->getInputSocket(i+1)->getConnection()->getFromSocket(), + plane_mask_operation->getInputSocket(i)); + output_plane->relinkConnections(plane_mask_operation->getOutputSocket()); + + graph->addOperation(plane_mask_operation); +} diff --git a/source/blender/compositor/operations/COM_PlaneTrackMaskOperation.h b/source/blender/compositor/nodes/COM_CornerPinNode.h index 7f763954079..b8b8a16384c 100644 --- a/source/blender/compositor/operations/COM_PlaneTrackMaskOperation.h +++ b/source/blender/compositor/nodes/COM_CornerPinNode.h @@ -1,6 +1,5 @@ - /* - * Copyright 2013, Blender Foundation. + * Copyright 2014, Blender Foundation. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License @@ -17,33 +16,26 @@ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * * Contributor: - * Sergey Sharybin + * Lukas Toenne */ -#ifndef _COM_PlaneTrackMaskOperation_h -#define _COM_PlaneTrackMaskOperation_h - -#include <string.h> - -#include "COM_PlaneTrackCommonOperation.h" - -#include "DNA_movieclip_types.h" -#include "DNA_tracking_types.h" +#ifndef _COM_CornerPinNode_h +#define _COM_CornerPinNode_h -#include "BLI_listbase.h" -#include "BLI_string.h" +#include "COM_Node.h" -class PlaneTrackMaskOperation : public PlaneTrackCommonOperation { -protected: - int m_osa; - float m_jitter[32][2]; +extern "C" { +#include "DNA_node_types.h" +} +/** + * @brief CornerPinNode + * @ingroup Node + */ +class CornerPinNode : public Node { public: - PlaneTrackMaskOperation(); - - void initExecution(); - - void executePixelSampled(float output[4], float x, float y, PixelSampler sampler); + CornerPinNode(bNode *editorNode); + void convertToOperations(ExecutionSystem *graph, CompositorContext *context); }; -#endif +#endif /* _COM_CornerPinNode_h */ diff --git a/source/blender/compositor/nodes/COM_PlaneTrackDeformNode.cpp b/source/blender/compositor/nodes/COM_PlaneTrackDeformNode.cpp index f52c696b772..944e04e4f4f 100644 --- a/source/blender/compositor/nodes/COM_PlaneTrackDeformNode.cpp +++ b/source/blender/compositor/nodes/COM_PlaneTrackDeformNode.cpp @@ -24,8 +24,7 @@ #include "COM_PlaneTrackDeformNode.h" #include "COM_ExecutionSystem.h" -#include "COM_PlaneTrackMaskOperation.h" -#include "COM_PlaneTrackWarpImageOperation.h" +#include "COM_PlaneTrackOperation.h" extern "C" { # include "BKE_node.h" diff --git a/source/blender/compositor/operations/COM_PlaneCornerPinOperation.cpp b/source/blender/compositor/operations/COM_PlaneCornerPinOperation.cpp new file mode 100644 index 00000000000..fe272000b6e --- /dev/null +++ b/source/blender/compositor/operations/COM_PlaneCornerPinOperation.cpp @@ -0,0 +1,223 @@ +/* + * Copyright 2014, Blender Foundation. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * Contributor: + * Lukas Toenne + */ + +#include "COM_PlaneCornerPinOperation.h" +#include "COM_ReadBufferOperation.h" + +#include "MEM_guardedalloc.h" + +#include "BLI_listbase.h" +#include "BLI_math.h" +#include "BLI_math_color.h" + +extern "C" { +# include "BLI_jitter.h" + +# include "BKE_node.h" +} + +static bool check_corners(float corners[4][2]) +{ + int i, next, prev; + float cross = 0.0f; + + for (i = 0; i < 4; i++) { + float v1[2], v2[2], cur_cross; + + next = (i + 1) % 4; + prev = (4 + i - 1) % 4; + + sub_v2_v2v2(v1, corners[i], corners[prev]); + sub_v2_v2v2(v2, corners[next], corners[i]); + + cur_cross = cross_v2v2(v1, v2); + if (fabsf(cur_cross) <= FLT_EPSILON) + return false; + + if (cross == 0.0f) + cross = cur_cross; + else if (cross * cur_cross < 0.0f) + return false; + } + + return true; +} + +static void readCornersFromSockets(rcti *rect, SocketReader *readers[4], float corners[4][2]) +{ + for (int i = 0; i < 4; ++i) { + float result[4] = {0.0f, 0.0f, 0.0f, 0.0f}; + readers[i]->readSampled(result, rect->xmin, rect->ymin, COM_PS_NEAREST); + corners[i][0] = result[0]; + corners[i][1] = result[1]; + } + + /* convexity check: + * concave corners need to be prevented, otherwise + * BKE_tracking_homography_between_two_quads will freeze + */ + if (!check_corners(corners)) { + /* simply revert to default corners + * there could be a more elegant solution, + * this prevents freezing at least. + */ + corners[0][0] = 0.0f; corners[0][1] = 0.0f; + corners[1][0] = 1.0f; corners[1][1] = 0.0f; + corners[2][0] = 1.0f; corners[2][1] = 1.0f; + corners[3][0] = 0.0f; corners[3][1] = 1.0f; + } +} + + +/* ******** PlaneCornerPinMaskOperation ******** */ + +PlaneCornerPinMaskOperation::PlaneCornerPinMaskOperation() : + PlaneDistortMaskOperation(), + m_corners_ready(false) +{ + addInputSocket(COM_DT_VECTOR); + addInputSocket(COM_DT_VECTOR); + addInputSocket(COM_DT_VECTOR); + addInputSocket(COM_DT_VECTOR); + + /* XXX this is stupid: we need to make this "complex", + * so we can use the initializeTileData function + * to read corners from input sockets ... + */ + setComplex(true); +} + +void PlaneCornerPinMaskOperation::initExecution() +{ + PlaneDistortMaskOperation::initExecution(); + + initMutex(); +} + +void PlaneCornerPinMaskOperation::deinitExecution() +{ + PlaneDistortMaskOperation::deinitExecution(); + + deinitMutex(); +} + +void *PlaneCornerPinMaskOperation::initializeTileData(rcti *rect) +{ + void *data = PlaneDistortMaskOperation::initializeTileData(rect); + + /* get corner values once, by reading inputs at (0,0) + * XXX this assumes invariable values (no image inputs), + * we don't have a nice generic system for that yet + */ + lockMutex(); + if (!m_corners_ready) { + SocketReader *readers[4] = { getInputSocketReader(0), + getInputSocketReader(1), + getInputSocketReader(2), + getInputSocketReader(3) }; + float corners[4][2]; + readCornersFromSockets(rect, readers, corners); + calculateCorners(corners, true); + + m_corners_ready = true; + } + unlockMutex(); + + return data; +} + +void PlaneCornerPinMaskOperation::determineResolution(unsigned int resolution[2], unsigned int preferredResolution[2]) +{ + resolution[0] = preferredResolution[0]; + resolution[1] = preferredResolution[1]; +} + + +/* ******** PlaneCornerPinWarpImageOperation ******** */ + +PlaneCornerPinWarpImageOperation::PlaneCornerPinWarpImageOperation() : + PlaneDistortWarpImageOperation(), + m_corners_ready(false) +{ + addInputSocket(COM_DT_VECTOR); + addInputSocket(COM_DT_VECTOR); + addInputSocket(COM_DT_VECTOR); + addInputSocket(COM_DT_VECTOR); +} + +void PlaneCornerPinWarpImageOperation::initExecution() +{ + PlaneDistortWarpImageOperation::initExecution(); + + initMutex(); +} + +void PlaneCornerPinWarpImageOperation::deinitExecution() +{ + PlaneDistortWarpImageOperation::deinitExecution(); + + deinitMutex(); +} + +void *PlaneCornerPinWarpImageOperation::initializeTileData(rcti *rect) +{ + void *data = PlaneDistortWarpImageOperation::initializeTileData(rect); + + /* get corner values once, by reading inputs at (0,0) + * XXX this assumes invariable values (no image inputs), + * we don't have a nice generic system for that yet + */ + lockMutex(); + if (!m_corners_ready) { + /* corner sockets start at index 1 */ + SocketReader *readers[4] = { getInputSocketReader(1), + getInputSocketReader(2), + getInputSocketReader(3), + getInputSocketReader(4) }; + float corners[4][2]; + readCornersFromSockets(rect, readers, corners); + calculateCorners(corners, true); + calculatePerspectiveMatrix(); + + m_corners_ready = true; + } + unlockMutex(); + + return data; +} + +bool PlaneCornerPinWarpImageOperation::determineDependingAreaOfInterest(rcti *input, ReadBufferOperation *readOperation, rcti *output) +{ + for (int i = 0; i < 4; ++i) + if (getInputOperation(i + 1)->determineDependingAreaOfInterest(input, readOperation, output)) + return true; + + /* XXX this is bad, but unavoidable with the current design: + * we don't know the actual corners and matrix at this point, + * so all we can do is get the full input image + */ + output->xmin = 0; + output->ymin = 0; + output->xmax = getInputOperation(0)->getWidth(); + output->ymax = getInputOperation(0)->getHeight(); + return true; +// return PlaneDistortWarpImageOperation::determineDependingAreaOfInterest(input, readOperation, output); +} diff --git a/source/blender/compositor/operations/COM_PlaneCornerPinOperation.h b/source/blender/compositor/operations/COM_PlaneCornerPinOperation.h new file mode 100644 index 00000000000..ed70d9c80a3 --- /dev/null +++ b/source/blender/compositor/operations/COM_PlaneCornerPinOperation.h @@ -0,0 +1,68 @@ + +/* + * Copyright 2014, Blender Foundation. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * Contributor: + * Lukas Toenne + */ + +#ifndef _COM_CornerPinWarpImageOperation_h +#define _COM_CornerPinWarpImageOperation_h + +#include <string.h> + +#include "COM_PlaneDistortCommonOperation.h" + +#include "DNA_movieclip_types.h" +#include "DNA_tracking_types.h" + +#include "BLI_listbase.h" +#include "BLI_string.h" + + +class PlaneCornerPinMaskOperation : public PlaneDistortMaskOperation { +private: + bool m_corners_ready; + +public: + PlaneCornerPinMaskOperation(); + + void initExecution(); + void deinitExecution(); + + void *initializeTileData(rcti *rect); + + void determineResolution(unsigned int resolution[2], unsigned int preferredResolution[2]); +}; + + +class PlaneCornerPinWarpImageOperation : public PlaneDistortWarpImageOperation { +private: + bool m_corners_ready; + +public: + PlaneCornerPinWarpImageOperation(); + + void initExecution(); + void deinitExecution(); + + void *initializeTileData(rcti *rect); + + bool determineDependingAreaOfInterest(rcti *input, ReadBufferOperation *readOperation, rcti *output); +}; + +#endif diff --git a/source/blender/compositor/operations/COM_PlaneTrackWarpImageOperation.cpp b/source/blender/compositor/operations/COM_PlaneDistortCommonOperation.cpp index 6579276fa9f..362d7f6d2d7 100644 --- a/source/blender/compositor/operations/COM_PlaneTrackWarpImageOperation.cpp +++ b/source/blender/compositor/operations/COM_PlaneDistortCommonOperation.cpp @@ -17,25 +17,26 @@ * * Contributor: * Sergey Sharybin + * Lukas Toenne */ -#include "COM_PlaneTrackWarpImageOperation.h" -#include "COM_ReadBufferOperation.h" +#include "COM_PlaneDistortCommonOperation.h" #include "MEM_guardedalloc.h" +extern "C" { #include "BLI_listbase.h" #include "BLI_math.h" #include "BLI_math_color.h" +#include "BLI_jitter.h" -extern "C" { -# include "BLI_jitter.h" - -# include "BKE_movieclip.h" -# include "BKE_node.h" -# include "BKE_tracking.h" +#include "BKE_movieclip.h" +#include "BKE_node.h" +#include "BKE_tracking.h" } +/* ******** PlaneDistort WarpImage ******** */ + BLI_INLINE void warpCoord(float x, float y, float matrix[3][3], float uv[2], float deriv[2][2]) { float vec[3] = {x, y, 1.0f}; @@ -49,7 +50,8 @@ BLI_INLINE void warpCoord(float x, float y, float matrix[3][3], float uv[2], flo deriv[1][1] = (matrix[1][1] - matrix[1][2] * uv[1]) / vec[2]; } -PlaneTrackWarpImageOperation::PlaneTrackWarpImageOperation() : PlaneTrackCommonOperation() +PlaneDistortWarpImageOperation::PlaneDistortWarpImageOperation() : + NodeOperation() { this->addInputSocket(COM_DT_COLOR, COM_SC_NO_RESIZE); this->addOutputSocket(COM_DT_COLOR); @@ -57,12 +59,24 @@ PlaneTrackWarpImageOperation::PlaneTrackWarpImageOperation() : PlaneTrackCommonO this->setComplex(true); } -void PlaneTrackWarpImageOperation::initExecution() +void PlaneDistortWarpImageOperation::calculateCorners(const float corners[4][2], bool normalized) { - PlaneTrackCommonOperation::initExecution(); - - this->m_pixelReader = this->getInputSocketReader(0); + if (normalized) { + for (int i = 0; i < 4; i++) { + this->m_frameSpaceCorners[i][0] = corners[i][0] * this->getWidth(); + this->m_frameSpaceCorners[i][1] = corners[i][1] * this->getHeight(); + } + } + else { + for (int i = 0; i < 4; i++) { + this->m_frameSpaceCorners[i][0] = corners[i][0]; + this->m_frameSpaceCorners[i][1] = corners[i][1]; + } + } +} +void PlaneDistortWarpImageOperation::calculatePerspectiveMatrix() +{ const int width = this->m_pixelReader->getWidth(); const int height = this->m_pixelReader->getHeight(); float frame_corners[4][2] = {{0.0f, 0.0f}, @@ -74,12 +88,17 @@ void PlaneTrackWarpImageOperation::initExecution() this->m_perspectiveMatrix); } -void PlaneTrackWarpImageOperation::deinitExecution() +void PlaneDistortWarpImageOperation::initExecution() +{ + this->m_pixelReader = this->getInputSocketReader(0); +} + +void PlaneDistortWarpImageOperation::deinitExecution() { this->m_pixelReader = NULL; } -void PlaneTrackWarpImageOperation::executePixelSampled(float output[4], float x, float y, PixelSampler sampler) +void PlaneDistortWarpImageOperation::executePixelSampled(float output[4], float x, float y, PixelSampler sampler) { float xy[2] = {x, y}; float uv[2]; @@ -90,12 +109,12 @@ void PlaneTrackWarpImageOperation::executePixelSampled(float output[4], float x, m_pixelReader->readFiltered(output, uv[0], uv[1], deriv[0], deriv[1], COM_PS_BILINEAR); } -void PlaneTrackWarpImageOperation::pixelTransform(const float xy[2], float r_uv[2], float r_deriv[2][2]) +void PlaneDistortWarpImageOperation::pixelTransform(const float xy[2], float r_uv[2], float r_deriv[2][2]) { warpCoord(xy[0], xy[1], m_perspectiveMatrix, r_uv, r_deriv); } -bool PlaneTrackWarpImageOperation::determineDependingAreaOfInterest(rcti *input, ReadBufferOperation *readOperation, rcti *output) +bool PlaneDistortWarpImageOperation::determineDependingAreaOfInterest(rcti *input, ReadBufferOperation *readOperation, rcti *output) { float UVs[4][2]; float deriv[2][2]; @@ -121,3 +140,55 @@ bool PlaneTrackWarpImageOperation::determineDependingAreaOfInterest(rcti *input, return NodeOperation::determineDependingAreaOfInterest(&newInput, readOperation, output); } + + +/* ******** PlaneDistort Mask ******** */ + +PlaneDistortMaskOperation::PlaneDistortMaskOperation() : + NodeOperation() +{ + addOutputSocket(COM_DT_VALUE); + + /* Currently hardcoded to 8 samples. */ + m_osa = 8; +} + +void PlaneDistortMaskOperation::calculateCorners(const float corners[4][2], bool normalized) +{ + if (normalized) { + for (int i = 0; i < 4; i++) { + this->m_frameSpaceCorners[i][0] = corners[i][0] * this->getWidth(); + this->m_frameSpaceCorners[i][1] = corners[i][1] * this->getHeight(); + } + } + else { + for (int i = 0; i < 4; i++) { + this->m_frameSpaceCorners[i][0] = corners[i][0]; + this->m_frameSpaceCorners[i][1] = corners[i][1]; + } + } +} + +void PlaneDistortMaskOperation::initExecution() +{ + BLI_jitter_init(m_jitter[0], m_osa); +} + +void PlaneDistortMaskOperation::executePixelSampled(float output[4], float x, float y, PixelSampler sampler) +{ + float point[2]; + + int inside_counter = 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, this->m_frameSpaceCorners[0], this->m_frameSpaceCorners[1], this->m_frameSpaceCorners[2]) || + isect_point_tri_v2(point, this->m_frameSpaceCorners[0], this->m_frameSpaceCorners[2], this->m_frameSpaceCorners[3])) + { + inside_counter++; + } + } + + output[0] = (float) inside_counter / this->m_osa; +} diff --git a/source/blender/compositor/operations/COM_PlaneTrackWarpImageOperation.h b/source/blender/compositor/operations/COM_PlaneDistortCommonOperation.h index ceb002c8039..ee2874c6b46 100644 --- a/source/blender/compositor/operations/COM_PlaneTrackWarpImageOperation.h +++ b/source/blender/compositor/operations/COM_PlaneDistortCommonOperation.h @@ -20,12 +20,12 @@ * Sergey Sharybin */ -#ifndef _COM_PlaneTrackWarpImageOperation_h -#define _COM_PlaneTrackWarpImageOperation_h +#ifndef _COM_PlaneTrackCommonOperation_h +#define _COM_PlaneTrackCommonOperation_h #include <string.h> -#include "COM_PlaneTrackCommonOperation.h" +#include "COM_NodeOperation.h" #include "DNA_movieclip_types.h" #include "DNA_tracking_types.h" @@ -33,13 +33,18 @@ #include "BLI_listbase.h" #include "BLI_string.h" -class PlaneTrackWarpImageOperation : public PlaneTrackCommonOperation { + +class PlaneDistortWarpImageOperation : public NodeOperation { protected: SocketReader *m_pixelReader; + float m_frameSpaceCorners[4][2]; /* Corners coordinates in pixel space. */ float m_perspectiveMatrix[3][3]; public: - PlaneTrackWarpImageOperation(); + PlaneDistortWarpImageOperation(); + + void calculateCorners(const float corners[4][2], bool normalized); + void calculatePerspectiveMatrix(); void initExecution(); void deinitExecution(); @@ -50,4 +55,21 @@ public: bool determineDependingAreaOfInterest(rcti *input, ReadBufferOperation *readOperation, rcti *output); }; + +class PlaneDistortMaskOperation : public NodeOperation { +protected: + int m_osa; + float m_jitter[32][2]; + float m_frameSpaceCorners[4][2]; /* Corners coordinates in pixel space. */ + +public: + PlaneDistortMaskOperation(); + + void calculateCorners(const float corners[4][2], bool normalized); + + void initExecution(); + + void executePixelSampled(float output[4], float x, float y, PixelSampler sampler); +}; + #endif diff --git a/source/blender/compositor/operations/COM_PlaneTrackMaskOperation.cpp b/source/blender/compositor/operations/COM_PlaneTrackMaskOperation.cpp deleted file mode 100644 index e43f6ab05b3..00000000000 --- a/source/blender/compositor/operations/COM_PlaneTrackMaskOperation.cpp +++ /dev/null @@ -1,70 +0,0 @@ -/* - * Copyright 2013, Blender Foundation. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - * - * Contributor: - * Sergey Sharybin - */ - -#include "COM_PlaneTrackMaskOperation.h" - -#include "MEM_guardedalloc.h" - -#include "BLI_listbase.h" -#include "BLI_math.h" -#include "BLI_math_color.h" - -extern "C" { -# include "BLI_jitter.h" - -# include "BKE_movieclip.h" -# include "BKE_node.h" -# include "BKE_tracking.h" -} - -PlaneTrackMaskOperation::PlaneTrackMaskOperation() : PlaneTrackCommonOperation() -{ - this->addOutputSocket(COM_DT_VALUE); - - /* Currently hardcoded to 8 samples. */ - this->m_osa = 8; -} - -void PlaneTrackMaskOperation::initExecution() -{ - PlaneTrackCommonOperation::initExecution(); - - BLI_jitter_init(this->m_jitter[0], this->m_osa); -} - -void PlaneTrackMaskOperation::executePixelSampled(float output[4], float x, float y, PixelSampler sampler) -{ - float point[2]; - - int inside_counter = 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, this->m_frameSpaceCorners[0], this->m_frameSpaceCorners[1], this->m_frameSpaceCorners[2]) || - isect_point_tri_v2(point, this->m_frameSpaceCorners[0], this->m_frameSpaceCorners[2], this->m_frameSpaceCorners[3])) - { - inside_counter++; - } - } - - output[0] = (float) inside_counter / this->m_osa; -} diff --git a/source/blender/compositor/operations/COM_PlaneTrackCommonOperation.cpp b/source/blender/compositor/operations/COM_PlaneTrackOperation.cpp index 5deb7b99bce..fec39cbfde0 100644 --- a/source/blender/compositor/operations/COM_PlaneTrackCommonOperation.cpp +++ b/source/blender/compositor/operations/COM_PlaneTrackOperation.cpp @@ -19,7 +19,8 @@ * Sergey Sharybin */ -#include "COM_PlaneTrackMaskOperation.h" +#include "COM_PlaneTrackOperation.h" +#include "COM_ReadBufferOperation.h" #include "MEM_guardedalloc.h" @@ -28,12 +29,16 @@ #include "BLI_math_color.h" extern "C" { +# include "BLI_jitter.h" + # include "BKE_movieclip.h" # include "BKE_node.h" # include "BKE_tracking.h" } -PlaneTrackCommonOperation::PlaneTrackCommonOperation() : NodeOperation() +/* ******** PlaneTrackCommon ******** */ + +PlaneTrackCommon::PlaneTrackCommon() { this->m_movieClip = NULL; this->m_framenumber = 0; @@ -41,55 +46,72 @@ PlaneTrackCommonOperation::PlaneTrackCommonOperation() : NodeOperation() this->m_planeTrackName[0] = '\0'; } -void PlaneTrackCommonOperation::initExecution() +void PlaneTrackCommon::readCornersFromTrack(float corners[4][2]) { MovieTracking *tracking; MovieTrackingObject *object; - memset(this->m_corners, 0, sizeof(this->m_corners)); - memset(this->m_frameSpaceCorners, 0, sizeof(this->m_frameSpaceCorners)); - if (!this->m_movieClip) return; - + tracking = &this->m_movieClip->tracking; - + object = BKE_tracking_object_get_named(tracking, this->m_trackingObjectName); if (object) { MovieTrackingPlaneTrack *plane_track; - + plane_track = BKE_tracking_plane_track_get_named(tracking, object, this->m_planeTrackName); - + if (plane_track) { MovieTrackingPlaneMarker *plane_marker; int clip_framenr = BKE_movieclip_remap_scene_to_clip_frame(this->m_movieClip, this->m_framenumber); - + plane_marker = BKE_tracking_plane_marker_get(plane_track, clip_framenr); - memcpy(this->m_corners, plane_marker->corners, sizeof(this->m_corners)); + copy_v2_v2(corners[0], plane_marker->corners[0]); + copy_v2_v2(corners[1], plane_marker->corners[1]); + copy_v2_v2(corners[2], plane_marker->corners[2]); + copy_v2_v2(corners[3], plane_marker->corners[3]); } } - - for (int i = 0; i < 4; i++) { - this->m_frameSpaceCorners[i][0] = this->m_corners[i][0] * this->getWidth(); - this->m_frameSpaceCorners[i][1] = this->m_corners[i][1] * this->getHeight(); - } } -void PlaneTrackCommonOperation::determineResolution(unsigned int resolution[2], unsigned int preferredResolution[2]) +void PlaneTrackCommon::determineResolution(unsigned int resolution[2], unsigned int preferredResolution[2]) { - NodeOperation::determineResolution(resolution, preferredResolution); - resolution[0] = 0; resolution[1] = 0; - + if (this->m_movieClip) { int width, height; MovieClipUser user = {0}; - + BKE_movieclip_user_set_frame(&user, this->m_framenumber); BKE_movieclip_get_size(this->m_movieClip, &user, &width, &height); - + resolution[0] = width; resolution[1] = height; } } + + +/* ******** PlaneTrackMaskOperation ******** */ + +void PlaneTrackMaskOperation::initExecution() +{ + PlaneDistortMaskOperation::initExecution(); + + float corners[4][2]; + readCornersFromTrack(corners); + calculateCorners(corners, true); +} + +/* ******** PlaneTrackWarpImageOperation ******** */ + +void PlaneTrackWarpImageOperation::initExecution() +{ + PlaneDistortWarpImageOperation::initExecution(); + + float corners[4][2]; + readCornersFromTrack(corners); + calculateCorners(corners, true); + calculatePerspectiveMatrix(); +} diff --git a/source/blender/compositor/operations/COM_PlaneTrackCommonOperation.h b/source/blender/compositor/operations/COM_PlaneTrackOperation.h index 705bdf4bd81..fdca760650a 100644 --- a/source/blender/compositor/operations/COM_PlaneTrackCommonOperation.h +++ b/source/blender/compositor/operations/COM_PlaneTrackOperation.h @@ -20,12 +20,12 @@ * Sergey Sharybin */ -#ifndef _COM_PlaneTrackCommonOperation_h -#define _COM_PlaneTrackCommonOperation_h +#ifndef _COM_PlaneTrackWarpImageOperation_h +#define _COM_PlaneTrackWarpImageOperation_h #include <string.h> -#include "COM_NodeOperation.h" +#include "COM_PlaneDistortCommonOperation.h" #include "DNA_movieclip_types.h" #include "DNA_tracking_types.h" @@ -33,30 +33,58 @@ #include "BLI_listbase.h" #include "BLI_string.h" -class PlaneTrackCommonOperation : public NodeOperation { +class PlaneTrackCommon { protected: MovieClip *m_movieClip; int m_framenumber; char m_trackingObjectName[64]; char m_planeTrackName[64]; - float m_corners[4][2]; /* Corners coordinates in normalized space. */ - float m_frameSpaceCorners[4][2]; /* Corners coordinates in pixel space. */ - - /** - * Determine the output resolution. The resolution is retrieved from the Renderer + /* note: this class is not an operation itself (to prevent virtual inheritance issues) + * implementation classes must make wrappers to use these methods, see below. */ + void readCornersFromTrack(float corners[4][2]); void determineResolution(unsigned int resolution[2], unsigned int preferredResolution[2]); public: - PlaneTrackCommonOperation(); + PlaneTrackCommon(); void setMovieClip(MovieClip *clip) {this->m_movieClip = clip;} void setTrackingObject(char *object) { BLI_strncpy(this->m_trackingObjectName, object, sizeof(this->m_trackingObjectName)); } void setPlaneTrackName(char *plane_track) { BLI_strncpy(this->m_planeTrackName, plane_track, sizeof(this->m_planeTrackName)); } void setFramenumber(int framenumber) {this->m_framenumber = framenumber;} +}; + +class PlaneTrackMaskOperation : public PlaneDistortMaskOperation, public PlaneTrackCommon { +public: + PlaneTrackMaskOperation() : + PlaneDistortMaskOperation(), + PlaneTrackCommon() + {} + + void initExecution(); + + void determineResolution(unsigned int resolution[2], unsigned int preferredResolution[2]) + { + PlaneTrackCommon::determineResolution(resolution, preferredResolution); + } +}; + + +class PlaneTrackWarpImageOperation : public PlaneDistortWarpImageOperation, public PlaneTrackCommon { +public: + PlaneTrackWarpImageOperation() : + PlaneDistortWarpImageOperation(), + PlaneTrackCommon() + {} + void initExecution(); + + void determineResolution(unsigned int resolution[2], unsigned int preferredResolution[2]) + { + PlaneTrackCommon::determineResolution(resolution, preferredResolution); + } }; #endif diff --git a/source/blender/editors/space_node/drawnode.c b/source/blender/editors/space_node/drawnode.c index 0cdb17cb2d4..d534eefb0a1 100644 --- a/source/blender/editors/space_node/drawnode.c +++ b/source/blender/editors/space_node/drawnode.c @@ -2280,6 +2280,10 @@ static void node_composit_buts_planetrackdeform(uiLayout *layout, bContext *C, P } } +static void node_composit_buts_cornerpin(uiLayout *UNUSED(layout), bContext *UNUSED(C), PointerRNA *UNUSED(ptr)) +{ +} + /* only once called */ static void node_composit_set_butfunc(bNodeType *ntype) { @@ -2501,6 +2505,9 @@ static void node_composit_set_butfunc(bNodeType *ntype) case CMP_NODE_PLANETRACKDEFORM: ntype->draw_buttons = node_composit_buts_planetrackdeform; break; + case CMP_NODE_CORNERPIN: + ntype->draw_buttons = node_composit_buts_cornerpin; + break; } } diff --git a/source/blender/nodes/CMakeLists.txt b/source/blender/nodes/CMakeLists.txt index 16671e84da0..fef6762d695 100644 --- a/source/blender/nodes/CMakeLists.txt +++ b/source/blender/nodes/CMakeLists.txt @@ -56,6 +56,7 @@ set(SRC composite/nodes/node_composite_colorbalance.c composite/nodes/node_composite_common.c composite/nodes/node_composite_composite.c + composite/nodes/node_composite_cornerpin.c composite/nodes/node_composite_crop.c composite/nodes/node_composite_curves.c composite/nodes/node_composite_despeckle.c diff --git a/source/blender/nodes/NOD_composite.h b/source/blender/nodes/NOD_composite.h index 78265154125..ad5f35b8faa 100644 --- a/source/blender/nodes/NOD_composite.h +++ b/source/blender/nodes/NOD_composite.h @@ -136,6 +136,7 @@ void register_node_type_cmp_switch(void); void register_node_type_cmp_pixelate(void); void register_node_type_cmp_trackpos(void); void register_node_type_cmp_planetrackdeform(void); +void register_node_type_cmp_cornerpin(void); void node_cmp_rlayers_force_hidden_passes(struct bNode *node); diff --git a/source/blender/nodes/NOD_static_types.h b/source/blender/nodes/NOD_static_types.h index f7f7118822f..b406ac49008 100644 --- a/source/blender/nodes/NOD_static_types.h +++ b/source/blender/nodes/NOD_static_types.h @@ -204,6 +204,7 @@ DefNode( CompositorNode, CMP_NODE_KEYING, def_cmp_keying, "KEYIN DefNode( CompositorNode, CMP_NODE_TRACKPOS, def_cmp_trackpos, "TRACKPOS", TrackPos, "Track Position", "" ) DefNode( CompositorNode, CMP_NODE_PIXELATE, 0, "PIXELATE", Pixelate, "Pixelate", "" ) DefNode( CompositorNode, CMP_NODE_PLANETRACKDEFORM,def_cmp_planetrackdeform,"PLANETRACKDEFORM",PlaneTrackDeform,"Plane Track Deform","" ) +DefNode( CompositorNode, CMP_NODE_CORNERPIN, 0, "CORNERPIN", CornerPin, "Corner Pin", "" ) DefNode( TextureNode, TEX_NODE_OUTPUT, def_tex_output, "OUTPUT", Output, "Output", "" ) DefNode( TextureNode, TEX_NODE_CHECKER, 0, "CHECKER", Checker, "Checker", "" ) diff --git a/source/blender/nodes/composite/nodes/node_composite_cornerpin.c b/source/blender/nodes/composite/nodes/node_composite_cornerpin.c new file mode 100644 index 00000000000..851bf92f176 --- /dev/null +++ b/source/blender/nodes/composite/nodes/node_composite_cornerpin.c @@ -0,0 +1,59 @@ +/* + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * The Original Code is Copyright (C) 2013 Blender Foundation. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): Blender Foundation, + * Sergey Sharybin + * + * ***** END GPL LICENSE BLOCK ***** + */ + +/** \file blender/nodes/composite/nodes/node_composite_planetrackdeform.c + * \ingroup cmpnodes + */ + + +#include "node_composite_util.h" + +static bNodeSocketTemplate inputs[] = { + { SOCK_RGBA, 1, N_("Image"), 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f, PROP_NONE}, + { SOCK_VECTOR, 1, N_("Upper Left"), 0.0f, 1.0f, 0.0f, 1.0f, 0.0f, 1.0f, PROP_NONE}, + { SOCK_VECTOR, 1, N_("Upper Right"), 1.0f, 1.0f, 0.0f, 1.0f, 0.0f, 1.0f, PROP_NONE}, + { SOCK_VECTOR, 1, N_("Lower Left"), 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f, PROP_NONE}, + { SOCK_VECTOR, 1, N_("Lower Right"), 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f, PROP_NONE}, + { -1, 0, "" } +}; + +static bNodeSocketTemplate outputs[] = { + { SOCK_RGBA, 0, N_("Image")}, + { SOCK_FLOAT, 0, N_("Plane")}, + { -1, 0, "" } +}; + +void register_node_type_cmp_cornerpin(void) +{ + static bNodeType ntype; + + cmp_node_type_base(&ntype, CMP_NODE_CORNERPIN, "Corner Pin", NODE_CLASS_DISTORT, 0); + node_type_socket_templates(&ntype, inputs, outputs); + + nodeRegisterType(&ntype); +} |