diff options
8 files changed, 187 insertions, 116 deletions
diff --git a/source/blender/compositor/CMakeLists.txt b/source/blender/compositor/CMakeLists.txt index efecf1a7565..ba897a87f97 100644 --- a/source/blender/compositor/CMakeLists.txt +++ b/source/blender/compositor/CMakeLists.txt @@ -580,6 +580,8 @@ set(SRC # Distort operation operations/COM_TranslateOperation.h operations/COM_TranslateOperation.cpp + operations/COM_WrapOperation.h + operations/COM_WrapOperation.cpp operations/COM_RotateOperation.h operations/COM_RotateOperation.cpp operations/COM_ScaleOperation.h diff --git a/source/blender/compositor/nodes/COM_TranslateNode.cpp b/source/blender/compositor/nodes/COM_TranslateNode.cpp index 887190b44b9..433ee2e5972 100644 --- a/source/blender/compositor/nodes/COM_TranslateNode.cpp +++ b/source/blender/compositor/nodes/COM_TranslateNode.cpp @@ -23,6 +23,7 @@ #include "COM_TranslateNode.h" #include "COM_TranslateOperation.h" +#include "COM_WrapOperation.h" #include "COM_ExecutionSystem.h" TranslateNode::TranslateNode(bNode *editorNode) : Node(editorNode) @@ -40,7 +41,16 @@ void TranslateNode::convertToOperations(ExecutionSystem *graph, CompositorContex bNode *bnode = this->getbNode(); NodeTranslateData *data = (NodeTranslateData *)bnode->storage; - operation->setWrapping(data->wrap_axis); + + if (data->wrap_axis) { + WrapOperation *wrapOperation = new WrapOperation(); + wrapOperation->setWrapping(data->wrap_axis); + inputSocket->relinkConnections(wrapOperation->getInputSocket(0), 0, graph); + addLink(graph, wrapOperation->getOutputSocket(), operation->getInputSocket(0)); + graph->addOperation(wrapOperation); + } else { + inputSocket->relinkConnections(operation->getInputSocket(0), 0, graph); + } if (data->relative) { const RenderData *rd = context->getRenderData(); @@ -50,7 +60,6 @@ void TranslateNode::convertToOperations(ExecutionSystem *graph, CompositorContex operation->setFactorXY(fx, fy); } - inputSocket->relinkConnections(operation->getInputSocket(0), 0, graph); inputXSocket->relinkConnections(operation->getInputSocket(1), 1, graph); inputYSocket->relinkConnections(operation->getInputSocket(2), 2, graph); outputSocket->relinkConnections(operation->getOutputSocket(0)); diff --git a/source/blender/compositor/operations/COM_TranslateOperation.cpp b/source/blender/compositor/operations/COM_TranslateOperation.cpp index 32b9398094d..9f6924eb428 100644 --- a/source/blender/compositor/operations/COM_TranslateOperation.cpp +++ b/source/blender/compositor/operations/COM_TranslateOperation.cpp @@ -44,11 +44,6 @@ void TranslateOperation::initExecution() this->m_inputYOperation = this->getInputSocketReader(2); ensureDelta(); - - //Calculate the relative offset once per execution, no need to do this per pixel - this->m_relativeOffsetX = fmodf(this->getDeltaX(), this->getWidth()); - this->m_relativeOffsetY = fmodf(this->getDeltaY(), this->getHeight()); - } void TranslateOperation::deinitExecution() @@ -66,27 +61,7 @@ void TranslateOperation::executePixel(float output[4], float x, float y, PixelSa float originalXPos = x - this->getDeltaX(); float originalYPos = y - this->getDeltaY(); - switch (m_wrappingType) { - case 0: - //Intentionally empty, originalXPos and originalYPos have been set before - break; - case 1: - // wrap only on the x-axis - originalXPos = this->getWrappedOriginalXPos(x); - break; - case 2: - // wrap only on the y-axis - originalYPos = this->getWrappedOriginalYPos(y); - break; - case 3: - // wrap on both - originalXPos = this->getWrappedOriginalXPos(x); - originalYPos = this->getWrappedOriginalYPos(y); - break; - } - this->m_inputOperation->read(output, originalXPos, originalYPos, sampler); - } bool TranslateOperation::determineDependingAreaOfInterest(rcti *input, ReadBufferOperation *readOperation, rcti *output) @@ -100,89 +75,9 @@ bool TranslateOperation::determineDependingAreaOfInterest(rcti *input, ReadBuffe newInput.ymin = input->ymin - this->getDeltaY(); newInput.ymax = input->ymax - this->getDeltaY(); - if (m_wrappingType == 1 || m_wrappingType == 3) { - // wrap only on the x-axis if tile is wrapping - newInput.xmin = getWrappedOriginalXPos(input->xmin); - newInput.xmax = getWrappedOriginalXPos(input->xmax); - if (newInput.xmin > newInput.xmax) { - newInput.xmin = 0; - newInput.xmax = this->getWidth(); - } - } - if (m_wrappingType == 2 || m_wrappingType == 3) { - // wrap only on the y-axis if tile is wrapping - newInput.ymin = getWrappedOriginalYPos(input->ymin); - newInput.ymax = getWrappedOriginalYPos(input->ymax); - if (newInput.ymin > newInput.ymax) { - newInput.ymin = 0; - newInput.ymax = this->getHeight(); - } - } - - return NodeOperation::determineDependingAreaOfInterest(&newInput, readOperation, output); } -void TranslateOperation::setWrapping(char wrapping_type) -{ - m_wrappingType = wrapping_type; -} - -float TranslateOperation::getWrappedOriginalXPos(float x) -{ - float originalXPos = 0; - - // Positive offset: Append image data from the left - if (this->m_relativeOffsetX > 0) { - if (x < this->m_relativeOffsetX) { - originalXPos = this->getWidth() - this->m_relativeOffsetX + x; - } - else { - originalXPos = x - this->m_relativeOffsetX; - } - } - else { - // Negative offset: Append image data from the right - if (x < (this->getWidth() + this->m_relativeOffsetX)) { - originalXPos = x - this->m_relativeOffsetX; - } - else { - originalXPos = x - (this->getWidth() + this->m_relativeOffsetX); - } - } - - while (originalXPos < 0) originalXPos += this->m_width; - return fmodf(originalXPos, this->getWidth()); -} - - -float TranslateOperation::getWrappedOriginalYPos(float y) -{ - float originalYPos = 0; - - // Positive offset: Append image data from the bottom - if (this->m_relativeOffsetY > 0) { - if (y < this->m_relativeOffsetY) { - originalYPos = this->getHeight() - this->m_relativeOffsetY + y; - } - else { - originalYPos = y - this->m_relativeOffsetY; - } - } - else { - // Negative offset: Append image data from the top - if (y < (this->getHeight() + this->m_relativeOffsetY)) { - originalYPos = y - this->m_relativeOffsetY; - } - else { - originalYPos = y - (this->getHeight() + this->m_relativeOffsetY); - } - } - - while (originalYPos < 0) originalYPos += this->m_height; - return fmodf(originalYPos, this->getHeight()); -} - void TranslateOperation::setFactorXY(float factorX, float factorY) { m_factorX = factorX; diff --git a/source/blender/compositor/operations/COM_TranslateOperation.h b/source/blender/compositor/operations/COM_TranslateOperation.h index accca527400..d53c3e464fc 100644 --- a/source/blender/compositor/operations/COM_TranslateOperation.h +++ b/source/blender/compositor/operations/COM_TranslateOperation.h @@ -37,7 +37,6 @@ private: float m_relativeOffsetY; float m_factorX; float m_factorY; - char m_wrappingType; public: TranslateOperation(); bool determineDependingAreaOfInterest(rcti *input, ReadBufferOperation *readOperation, rcti *output); @@ -60,10 +59,6 @@ public: } } - void setWrapping(char wrapping_type); - float getWrappedOriginalXPos(float x); - float getWrappedOriginalYPos(float y); - void setFactorXY(float factorX, float factorY); }; diff --git a/source/blender/compositor/operations/COM_WrapOperation.cpp b/source/blender/compositor/operations/COM_WrapOperation.cpp new file mode 100644 index 00000000000..37a93520c7c --- /dev/null +++ b/source/blender/compositor/operations/COM_WrapOperation.cpp @@ -0,0 +1,117 @@ +/* + * Copyright 2011, 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: + * Jeroen Bakker + * Monique Dewanchand + * Thomas Beck (plasmasolutions.de) + */ + +#include "COM_WrapOperation.h" + +WrapOperation::WrapOperation() : NodeOperation() +{ + this->addInputSocket(COM_DT_COLOR); + this->addOutputSocket(COM_DT_COLOR); + this->setResolutionInputSocketIndex(0); + this->m_inputOperation = NULL; +} +void WrapOperation::initExecution() +{ + this->m_inputOperation = this->getInputSocketReader(0); +} + +void WrapOperation::deinitExecution() +{ + this->m_inputOperation = NULL; +} + +inline float WrapOperation::getWrappedOriginalXPos(float x) +{ + while (x < 0) x += this->m_width; + return fmodf(x, this->getWidth()); +} + +inline float WrapOperation::getWrappedOriginalYPos(float y) +{ + while (y < 0) y += this->m_height; + return fmodf(y, this->getHeight()); +} + +void WrapOperation::executePixel(float output[4], float x, float y, PixelSampler sampler) +{ + float nx, ny; + nx = x; + ny = y; + switch (m_wrappingType) { + case CMP_NODE_WRAP_NONE: + //Intentionally empty, originalXPos and originalYPos have been set before + break; + case CMP_NODE_WRAP_X: + // wrap only on the x-axis + nx = this->getWrappedOriginalXPos(x); + break; + case CMP_NODE_WRAP_Y: + // wrap only on the y-axis + ny = this->getWrappedOriginalYPos(y); + break; + case CMP_NODE_WRAP_XY: + // wrap on both + nx = this->getWrappedOriginalXPos(x); + ny = this->getWrappedOriginalYPos(y); + break; + } + + this->m_inputOperation->read(output, nx, ny, sampler); + +} + +bool WrapOperation::determineDependingAreaOfInterest(rcti *input, ReadBufferOperation *readOperation, rcti *output) +{ + rcti newInput; + + newInput.xmin = input->xmin; + newInput.xmax = input->xmax; + newInput.ymin = input->ymin; + newInput.ymax = input->ymax; + + if (m_wrappingType == 1 || m_wrappingType == 3) { + // wrap only on the x-axis if tile is wrapping + newInput.xmin = getWrappedOriginalXPos(input->xmin); + newInput.xmax = getWrappedOriginalXPos(input->xmax); + if (newInput.xmin > newInput.xmax) { + newInput.xmin = 0; + newInput.xmax = this->getWidth(); + } + } + if (m_wrappingType == 2 || m_wrappingType == 3) { + // wrap only on the y-axis if tile is wrapping + newInput.ymin = getWrappedOriginalYPos(input->ymin); + newInput.ymax = getWrappedOriginalYPos(input->ymax); + if (newInput.ymin > newInput.ymax) { + newInput.ymin = 0; + newInput.ymax = this->getHeight(); + } + } + + return NodeOperation::determineDependingAreaOfInterest(&newInput, readOperation, output); +} + +void WrapOperation::setWrapping(int wrapping_type) +{ + m_wrappingType = wrapping_type; +} diff --git a/source/blender/compositor/operations/COM_WrapOperation.h b/source/blender/compositor/operations/COM_WrapOperation.h new file mode 100644 index 00000000000..b84d85e7b5d --- /dev/null +++ b/source/blender/compositor/operations/COM_WrapOperation.h @@ -0,0 +1,47 @@ +/* + * Copyright 2011, 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: + * Jeroen Bakker + * Monique Dewanchand + */ + +#ifndef _COM_WrapOperation_h_ +#define _COM_WrapOperation_h_ + +#include "COM_NodeOperation.h" + +class WrapOperation : public NodeOperation { +private: + SocketReader *m_inputOperation; + int m_wrappingType; +public: + WrapOperation(); + bool determineDependingAreaOfInterest(rcti *input, ReadBufferOperation *readOperation, rcti *output); + void executePixel(float output[4], float x, float y, PixelSampler sampler); + + void initExecution(); + void deinitExecution(); + + void setWrapping(int wrapping_type); + float getWrappedOriginalXPos(float x); + float getWrappedOriginalYPos(float y); + + void setFactorXY(float factorX, float factorY); +}; + +#endif diff --git a/source/blender/makesdna/DNA_node_types.h b/source/blender/makesdna/DNA_node_types.h index 116b2327d29..7f2e388cd69 100644 --- a/source/blender/makesdna/DNA_node_types.h +++ b/source/blender/makesdna/DNA_node_types.h @@ -844,6 +844,12 @@ typedef struct NodeShaderNormalMap { #define CMP_NODE_BLUR_ASPECT_Y 1 #define CMP_NODE_BLUR_ASPECT_X 2 +/* wrapping */ +#define CMP_NODE_WRAP_NONE 0 +#define CMP_NODE_WRAP_X 1 +#define CMP_NODE_WRAP_Y 2 +#define CMP_NODE_WRAP_XY 3 + #define CMP_NODE_MASK_MBLUR_SAMPLES_MAX 64 #endif diff --git a/source/blender/makesrna/intern/rna_nodetree.c b/source/blender/makesrna/intern/rna_nodetree.c index fdae2979432..fee4b429a11 100644 --- a/source/blender/makesrna/intern/rna_nodetree.c +++ b/source/blender/makesrna/intern/rna_nodetree.c @@ -4228,10 +4228,10 @@ static void def_cmp_trackpos(StructRNA *srna) static void def_cmp_translate(StructRNA *srna) { static EnumPropertyItem translate_items[] = { - {0, "NONE", 0, "None", "No wrapping on X and Y"}, - {1, "XAXIS", 0, "X Axis", "Wrap all pixels on the X axis"}, - {2, "YAXIS", 0, "Y Axis", "Wrap all pixels on the Y axis"}, - {3, "BOTH", 0, "Both Axes", "Wrap all pixels on both axes"}, + {CMP_NODE_WRAP_NONE, "NONE", 0, "None", "No wrapping on X and Y"}, + {CMP_NODE_WRAP_X, "XAXIS", 0, "X Axis", "Wrap all pixels on the X axis"}, + {CMP_NODE_WRAP_Y, "YAXIS", 0, "Y Axis", "Wrap all pixels on the Y axis"}, + {CMP_NODE_WRAP_XY, "BOTH", 0, "Both Axes", "Wrap all pixels on both axes"}, {0, NULL, 0, NULL, NULL} }; |