├── .gitignore ├── CHOP ├── BasicFilterCHOP │ ├── BasicFilterCHOP.cpp │ ├── BasicFilterCHOP.h │ ├── BasicFilterCHOP.sln │ ├── BasicFilterCHOP.vcxproj │ ├── CHOP_CPlusPlusBase.h │ ├── CPlusPlus_Common.h │ ├── Parameters.cpp │ ├── Parameters.h │ └── README.md ├── BasicGeneratorCHOP │ ├── BasicGeneratorCHOP.cpp │ ├── BasicGeneratorCHOP.h │ ├── BasicGeneratorCHOP.sln │ ├── BasicGeneratorCHOP.vcxproj │ ├── CHOP_CPlusPlusBase.h │ ├── CPlusPlus_Common.h │ ├── Parameters.cpp │ ├── Parameters.h │ └── README.md ├── OneEuroCHOP │ ├── CHOP_CPlusPlusBase.h │ ├── CPlusPlus_Common.h │ ├── OneEuroCHOP.cpp │ ├── OneEuroCHOP.h │ ├── OneEuroCHOP.sln │ ├── OneEuroCHOP.vcxproj │ ├── OneEuroImpl.cpp │ ├── OneEuroImpl.h │ ├── Parameters.cpp │ ├── Parameters.h │ └── README.md ├── TimeSliceFilterCHOP │ ├── CHOP_CPlusPlusBase.h │ ├── CPlusPlus_Common.h │ ├── GL_Extensions.h │ ├── Parameters.cpp │ ├── Parameters.h │ ├── README.md │ ├── TimeSliceFilterCHOP.cpp │ ├── TimeSliceFilterCHOP.h │ ├── TimeSliceFilterCHOP.sln │ └── TimeSliceFilterCHOP.vcxproj └── TimeSliceGeneratorCHOP │ ├── CHOP_CPlusPlusBase.h │ ├── CPlusPlus_Common.h │ ├── Parameters.cpp │ ├── Parameters.h │ ├── README.md │ ├── TimeSliceGeneratorCHOP.cpp │ ├── TimeSliceGeneratorCHOP.h │ ├── TimeSliceGeneratorCHOP.sln │ └── TimeSliceGeneratorCHOP.vcxproj ├── DAT ├── FilterDAT │ ├── CPlusPlus_Common.h │ ├── DAT_CPlusPlusBase.h │ ├── FilterDAT.cpp │ ├── FilterDAT.h │ ├── FilterDAT.sln │ ├── FilterDAT.vcxproj │ ├── Parameters.cpp │ ├── Parameters.h │ └── README.md └── GeneratorDAT │ ├── CPlusPlus_Common.h │ ├── DATGenerator.vcxproj │ ├── DAT_CPlusPlusBase.h │ ├── GeneratorDAT.cpp │ ├── GeneratorDAT.h │ ├── GeneratorDAT.sln │ ├── Parameters.cpp │ ├── Parameters.h │ └── README.md ├── LICENSE.md ├── README.md ├── SOP ├── FilterSOP │ ├── CPlusPlus_Common.h │ ├── FilterSOP.cpp │ ├── FilterSOP.h │ ├── FilterSOP.sln │ ├── FilterSOP.vcxproj │ ├── GL_Extensions.h │ ├── Parameters.cpp │ ├── Parameters.h │ ├── README.md │ └── SOP_CPlusPlusBase.h ├── GeneratorSOP │ ├── CPlusPlus_Common.h │ ├── GL_Extensions.h │ ├── GeneratorSOP.cpp │ ├── GeneratorSOP.h │ ├── GeneratorSOP.sln │ ├── GeneratorSOP.vcxproj │ ├── Parameters.cpp │ ├── Parameters.h │ ├── README.md │ ├── SOP_CPlusPlusBase.h │ ├── ShapeGenerator.cpp │ └── ShapeGenerator.h ├── IntersectPointsSOP │ ├── CPlusPlus_Common.h │ ├── GL_Extensions.h │ ├── IntersectPointsSOP.cpp │ ├── IntersectPointsSOP.h │ ├── IntersectPointsSOP.sln │ ├── IntersectPointsSOP.vcxproj │ ├── Parameters.cpp │ ├── Parameters.h │ ├── README.md │ └── SOP_CPlusPlusBase.h ├── SpiralSOP │ ├── CPlusPlus_Common.h │ ├── GL_Extensions.h │ ├── Parameters.cpp │ ├── Parameters.h │ ├── README.md │ ├── SOP_CPlusPlusBase.h │ ├── SpiralSOP.cpp │ ├── SpiralSOP.h │ ├── SpiralSOP.sln │ └── SpiralSOP.vcxproj ├── SprinkleSOP │ ├── CPlusPlus_Common.h │ ├── GL_Extensions.h │ ├── Parameters.cpp │ ├── Parameters.h │ ├── README.md │ ├── RandomPointsBuffer.cpp │ ├── RandomPointsBuffer.h │ ├── SOP_CPlusPlusBase.h │ ├── SprinkleSOP.cpp │ ├── SprinkleSOP.h │ ├── SprinkleSOP.sln │ ├── SprinkleSOP.vcxproj │ ├── VolSprinkleTree.cpp │ └── VolSprinkleTree.h └── WrapPointsSOP │ ├── CPlusPlus_Common.h │ ├── GL_Extensions.h │ ├── Parameters.cpp │ ├── Parameters.h │ ├── README.md │ ├── SOP_CPlusPlusBase.h │ ├── WrapPointsSOP.cpp │ ├── WrapPointsSOP.h │ ├── WrapPointsSOP.sln │ └── WrapPointsSOP.vcxproj ├── TOP ├── BasicFilterTOP │ ├── BasicFilterTOP.cpp │ ├── BasicFilterTOP.h │ ├── BasicFilterTOP.sln │ ├── BasicFilterTOP.vcxproj │ ├── CPlusPlus_Common.h │ ├── FilterWork.cpp │ ├── FilterWork.h │ ├── Parameters.cpp │ ├── Parameters.h │ ├── README.md │ ├── TOP_CPlusPlusBase.h │ ├── ThreadManager.cpp │ └── ThreadManager.h ├── CannyEdgeTOP │ ├── CPlusPlus_Common.h │ ├── CannyEdgeTOP.cpp │ ├── CannyEdgeTOP.h │ ├── CannyEdgeTOP.sln │ ├── CannyEdgeTOP.vcxproj │ ├── GpuUtils.cu │ ├── GpuUtils.cuh │ ├── Parameters.cpp │ ├── Parameters.h │ ├── README.md │ └── TOP_CPlusPlusBase.h ├── DistanceTransformTOP │ ├── CPlusPlus_Common.h │ ├── DistanceTransformTOP.cpp │ ├── DistanceTransformTOP.h │ ├── DistanceTransformTOP.sln │ ├── DistanceTransformTOP.vcxproj │ ├── Parameters.cpp │ ├── Parameters.h │ ├── README.md │ └── TOP_CPlusPlusBase.h ├── ONNXCandyStyleTOP │ ├── CPlusPlus_Common.h │ ├── ONNXCandyStyleTOP.cpp │ ├── ONNXCandyStyleTOP.h │ ├── ONNXCandyStyleTOP.sln │ ├── ONNXCandyStyleTOP.vcxproj │ ├── README.md │ ├── TOP_CPlusPlusBase.h │ └── kernel.cu ├── ObjectDetectorTOP │ ├── CPlusPlus_Common.h │ ├── ObjectDetectorTOP.cpp │ ├── ObjectDetectorTOP.h │ ├── ObjectDetectorTOP.sln │ ├── ObjectDetectorTOP.vcxproj │ ├── Parameters.cpp │ ├── Parameters.h │ ├── README.md │ └── TOP_CPlusPlusBase.h ├── OpticalFlowCPUTOP │ ├── CPlusPlus_Common.h │ ├── OpticalFlowCPUTOP.cpp │ ├── OpticalFlowCPUTOP.h │ ├── OpticalFlowCPUTOP.sln │ ├── OpticalFlowCPUTOP.vcxproj │ ├── Parameters.cpp │ ├── Parameters.h │ ├── README.md │ └── TOP_CPlusPlusBase.h └── SpectrumTOP │ ├── CPlusPlus_Common.h │ ├── GpuUtils.cu │ ├── GpuUtils.cuh │ ├── Parameters.cpp │ ├── Parameters.h │ ├── README.md │ ├── SpectrumTOP.cpp │ ├── SpectrumTOP.h │ ├── SpectrumTOP.sln │ ├── SpectrumTOP.vcxproj │ └── TOP_CPlusPlusBase.h └── images ├── image1.png ├── image10.png ├── image2.png ├── image3.png ├── image4.png ├── image5.png ├── image6.png ├── image7.png ├── image8.png └── image9.png /.gitignore: -------------------------------------------------------------------------------- 1 | **/Release/ 2 | **/Debug/ 3 | **/.vs/ 4 | *.user -------------------------------------------------------------------------------- /CHOP/BasicFilterCHOP/BasicFilterCHOP.cpp: -------------------------------------------------------------------------------- 1 | /* Shared Use License: This file is owned by Derivative Inc. (Derivative) 2 | * and can only be used, and/or modified for use, in conjunction with 3 | * Derivative's TouchDesigner software, and only if you are a licensee who has 4 | * accepted Derivative's TouchDesigner license or assignment agreement 5 | * (which also govern the use of this file). You may share or redistribute 6 | * a modified version of this file provided the following conditions are met: 7 | * 8 | * 1. The shared file or redistribution must retain the information set out 9 | * above and this list of conditions. 10 | * 2. Derivative's name (Derivative Inc.) or its trademarks may not be used 11 | * to endorse or promote products derived from this file without specific 12 | * prior written permission from Derivative. 13 | */ 14 | 15 | #include "BasicFilterCHOP.h" 16 | 17 | #include 18 | #include 19 | 20 | // These functions are basic C function, which the DLL loader can find 21 | // much easier than finding a C++ Class. 22 | // The DLLEXPORT prefix is needed so the compile exports these functions from the .dll 23 | // you are creating 24 | extern "C" 25 | { 26 | 27 | DLLEXPORT 28 | void 29 | FillCHOPPluginInfo(CHOP_PluginInfo *info) 30 | { 31 | // For more information on CHOP_PluginInfo see CHOP_CPlusPlusBase.h 32 | 33 | // Always set this to CHOPCPlusPlusAPIVersion. 34 | info->apiVersion = CHOPCPlusPlusAPIVersion; 35 | 36 | // For more information on OP_CustomOPInfo see CPlusPlus_Common.h 37 | OP_CustomOPInfo& customInfo = info->customOPInfo; 38 | 39 | // Unique name of the node which starts with an upper case letter, followed by lower case letters or numbers 40 | customInfo.opType->setString("Basicfilter"); 41 | // English readable name 42 | customInfo.opLabel->setString("Basic Filter"); 43 | // Information of the author of the node 44 | customInfo.authorName->setString("Author Name"); 45 | customInfo.authorEmail->setString("email@email.ca"); 46 | 47 | // This CHOP takes one input 48 | customInfo.minInputs = 1; 49 | customInfo.maxInputs = 1; 50 | } 51 | 52 | DLLEXPORT 53 | CHOP_CPlusPlusBase* 54 | CreateCHOPInstance(const OP_NodeInfo* info) 55 | { 56 | // Return a new instance of your class every time this is called. 57 | // It will be called once per CHOP that is using the .dll 58 | return new BasicFilterCHOP(info); 59 | } 60 | 61 | DLLEXPORT 62 | void 63 | DestroyCHOPInstance(CHOP_CPlusPlusBase* instance) 64 | { 65 | // Delete the instance here, this will be called when 66 | // Touch is shutting down, when the CHOP using that instance is deleted, or 67 | // if the CHOP loads a different DLL 68 | delete (BasicFilterCHOP*)instance; 69 | } 70 | 71 | }; 72 | 73 | 74 | BasicFilterCHOP::BasicFilterCHOP(const OP_NodeInfo*) 75 | { 76 | 77 | } 78 | 79 | BasicFilterCHOP::~BasicFilterCHOP() 80 | { 81 | 82 | } 83 | 84 | void 85 | BasicFilterCHOP::getGeneralInfo(CHOP_GeneralInfo* ginfo, const OP_Inputs*, void*) 86 | { 87 | // This will cause the node to cook every frame if the output is used 88 | ginfo->cookEveryFrameIfAsked = false; 89 | 90 | // The output matches the sample and channels of the input with index 0 91 | ginfo->inputMatchIndex = 0; 92 | 93 | ginfo->timeslice = false; 94 | } 95 | 96 | bool 97 | BasicFilterCHOP::getOutputInfo(CHOP_OutputInfo* info, const OP_Inputs* inputs, void*) 98 | { 99 | // We return false since the signal matches the input 0 100 | return false; 101 | } 102 | 103 | void 104 | BasicFilterCHOP::getChannelName(int32_t index, OP_String *name, const OP_Inputs*, void*) 105 | { 106 | name->setString("chan1"); 107 | } 108 | 109 | void 110 | BasicFilterCHOP::execute(CHOP_Output* output, 111 | const OP_Inputs* inputs, 112 | void*) 113 | { 114 | // Get all Parameters 115 | bool applyScale = myParms.evalApplyscale(inputs); 116 | double scale = myParms.evalScale(inputs); 117 | bool applyOffset = myParms.evalApplyoffset(inputs); 118 | double offset = myParms.evalOffset(inputs); 119 | 120 | inputs->enablePar(ScaleName, applyScale); 121 | inputs->enablePar(OffsetName, applyOffset); 122 | 123 | const OP_CHOPInput* input = inputs->getInputCHOP(0); 124 | 125 | if (!input) 126 | return; 127 | 128 | // We know input and output have the same numChannels since we returned 129 | // false in getOutputInfo and it is not timeSliced 130 | for (int i = 0; i < output->numChannels; ++i) 131 | { 132 | for (int j = 0; j < output->numSamples; ++j) 133 | { 134 | output->channels[i][j] = static_cast(input->channelData[i][j] * scale + offset); 135 | } 136 | } 137 | } 138 | 139 | void 140 | BasicFilterCHOP::setupParameters(OP_ParameterManager* manager, void*) 141 | { 142 | myParms.setup(manager); 143 | } 144 | -------------------------------------------------------------------------------- /CHOP/BasicFilterCHOP/BasicFilterCHOP.h: -------------------------------------------------------------------------------- 1 | /* Shared Use License: This file is owned by Derivative Inc. (Derivative) 2 | * and can only be used, and/or modified for use, in conjunction with 3 | * Derivative's TouchDesigner software, and only if you are a licensee who has 4 | * accepted Derivative's TouchDesigner license or assignment agreement 5 | * (which also govern the use of this file). You may share or redistribute 6 | * a modified version of this file provided the following conditions are met: 7 | * 8 | * 1. The shared file or redistribution must retain the information set out 9 | * above and this list of conditions. 10 | * 2. Derivative's name (Derivative Inc.) or its trademarks may not be used 11 | * to endorse or promote products derived from this file without specific 12 | * prior written permission from Derivative. 13 | */ 14 | 15 | #ifndef __BasicFilterCHOP__ 16 | #define __BasicFilterCHOP__ 17 | 18 | #include "CHOP_CPlusPlusBase.h" 19 | #include "Parameters.h" 20 | 21 | using namespace TD; 22 | 23 | /* 24 | This example implements a CHOP which takes the following parameters: 25 | - Apply Scale: If On, scale values. 26 | - Scale: A scalar by which the output signal is scaled. 27 | - Apply Offset: If On, offset values. 28 | - Offset: A scalar by which the output is offsetted. 29 | 30 | The output values are: scale*(channel) + offset 31 | 32 | This CHOP is a filter and it takes exactly one input. 33 | */ 34 | 35 | // Check methods [getNumInfoCHOPChans, getInfoCHOPChan, getInfoDATSize, getInfoDATEntries] 36 | // if you want to output values to the Info CHOP/DAT 37 | 38 | // To get more help about these functions, look at CHOP_CPlusPlusBase.h 39 | class BasicFilterCHOP : public CHOP_CPlusPlusBase 40 | { 41 | public: 42 | BasicFilterCHOP(const OP_NodeInfo* info); 43 | virtual ~BasicFilterCHOP(); 44 | 45 | virtual void getGeneralInfo(CHOP_GeneralInfo*, const TD::OP_Inputs*, void*) override; 46 | virtual bool getOutputInfo(CHOP_OutputInfo*, const TD::OP_Inputs*, void*) override; 47 | virtual void getChannelName(int32_t index, OP_String *name, const TD::OP_Inputs*, void*) override; 48 | 49 | virtual void execute(CHOP_Output*, const TD::OP_Inputs*, void*) override; 50 | 51 | virtual void setupParameters(TD::OP_ParameterManager* manager, void*) override; 52 | 53 | private: 54 | 55 | Parameters myParms; 56 | }; 57 | 58 | #endif 59 | -------------------------------------------------------------------------------- /CHOP/BasicFilterCHOP/BasicFilterCHOP.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio Version 16 4 | VisualStudioVersion = 16.0.30011.22 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "BasicFilterCHOP", "BasicFilterCHOP.vcxproj", "{3F5BEECD-FA36-459F-91B8-BB481A67EF44}" 7 | EndProject 8 | Global 9 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 10 | Debug|x64 = Debug|x64 11 | Release|x64 = Release|x64 12 | EndGlobalSection 13 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 14 | {3F5BEECD-FA36-459F-91B8-BB481A67EF44}.Debug|x64.ActiveCfg = Debug|x64 15 | {3F5BEECD-FA36-459F-91B8-BB481A67EF44}.Debug|x64.Build.0 = Debug|x64 16 | {3F5BEECD-FA36-459F-91B8-BB481A67EF44}.Release|x64.ActiveCfg = Release|x64 17 | {3F5BEECD-FA36-459F-91B8-BB481A67EF44}.Release|x64.Build.0 = Release|x64 18 | EndGlobalSection 19 | GlobalSection(SolutionProperties) = preSolution 20 | HideSolutionNode = FALSE 21 | EndGlobalSection 22 | GlobalSection(ExtensibilityGlobals) = postSolution 23 | SolutionGuid = {CDCA304D-7173-47CC-BC43-257E4444266C} 24 | EndGlobalSection 25 | EndGlobal 26 | -------------------------------------------------------------------------------- /CHOP/BasicFilterCHOP/Parameters.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include "CPlusPlus_Common.h" 4 | #include "Parameters.h" 5 | 6 | #pragma region Evals 7 | 8 | bool 9 | Parameters::evalApplyscale(const TD::OP_Inputs* inputs) 10 | { 11 | return inputs->getParInt(ApplyscaleName) ? true : false; 12 | } 13 | 14 | double 15 | Parameters::evalScale(const TD::OP_Inputs* inputs) 16 | { 17 | return inputs->getParDouble(ScaleName); 18 | } 19 | 20 | bool 21 | Parameters::evalApplyoffset(const TD::OP_Inputs* inputs) 22 | { 23 | return inputs->getParInt(ApplyoffsetName) ? true : false; 24 | } 25 | 26 | double 27 | Parameters::evalOffset(const TD::OP_Inputs* inputs) 28 | { 29 | return inputs->getParDouble(OffsetName); 30 | } 31 | 32 | 33 | #pragma endregion 34 | 35 | #pragma region Setup 36 | 37 | void 38 | Parameters::setup(TD::OP_ParameterManager* manager) 39 | { 40 | { 41 | TD::OP_NumericParameter p; 42 | p.name = ApplyscaleName; 43 | p.label = ApplyscaleLabel; 44 | p.page = "Filter"; 45 | p.defaultValues[0] = false; 46 | 47 | TD::OP_ParAppendResult res = manager->appendToggle(p); 48 | 49 | assert(res == TD::OP_ParAppendResult::Success); 50 | } 51 | 52 | { 53 | TD::OP_NumericParameter p; 54 | p.name = ScaleName; 55 | p.label = ScaleLabel; 56 | p.page = "Filter"; 57 | p.defaultValues[0] = 1.0; 58 | p.minSliders[0] = -10.0; 59 | p.maxSliders[0] = 10.0; 60 | p.minValues[0] = 0.0; 61 | p.maxValues[0] = 1.0; 62 | p.clampMins[0] = false; 63 | p.clampMaxes[0] = false; 64 | TD::OP_ParAppendResult res = manager->appendFloat(p); 65 | 66 | assert(res == TD::OP_ParAppendResult::Success); 67 | } 68 | 69 | { 70 | TD::OP_NumericParameter p; 71 | p.name = ApplyoffsetName; 72 | p.label = ApplyoffsetLabel; 73 | p.page = "Filter"; 74 | p.defaultValues[0] = false; 75 | 76 | TD::OP_ParAppendResult res = manager->appendToggle(p); 77 | 78 | assert(res == TD::OP_ParAppendResult::Success); 79 | } 80 | 81 | { 82 | TD::OP_NumericParameter p; 83 | p.name = OffsetName; 84 | p.label = OffsetLabel; 85 | p.page = "Filter"; 86 | p.defaultValues[0] = 0.0; 87 | p.minSliders[0] = -10.0; 88 | p.maxSliders[0] = 10.0; 89 | p.minValues[0] = 0.0; 90 | p.maxValues[0] = 1.0; 91 | p.clampMins[0] = false; 92 | p.clampMaxes[0] = false; 93 | TD::OP_ParAppendResult res = manager->appendFloat(p); 94 | 95 | assert(res == TD::OP_ParAppendResult::Success); 96 | } 97 | 98 | 99 | } 100 | 101 | #pragma endregion -------------------------------------------------------------------------------- /CHOP/BasicFilterCHOP/Parameters.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | class TD::OP_Inputs; 6 | class TD::OP_ParameterManager; 7 | 8 | #pragma region ParNames and ParLabels 9 | 10 | // Names of the parameters 11 | 12 | constexpr static char ApplyscaleName[] = "Applyscale"; 13 | constexpr static char ApplyscaleLabel[] = "Apply Scale"; 14 | 15 | constexpr static char ScaleName[] = "Scale"; 16 | constexpr static char ScaleLabel[] = "Scale"; 17 | 18 | constexpr static char ApplyoffsetName[] = "Applyoffset"; 19 | constexpr static char ApplyoffsetLabel[] = "Apply Offset"; 20 | 21 | constexpr static char OffsetName[] = "Offset"; 22 | constexpr static char OffsetLabel[] = "Offset"; 23 | 24 | 25 | #pragma endregion 26 | 27 | #pragma region Menus 28 | #pragma endregion 29 | 30 | 31 | #pragma region Parameters 32 | class Parameters 33 | { 34 | public: 35 | static void setup(TD::OP_ParameterManager*); 36 | 37 | // Apply Scale 38 | static bool evalApplyscale(const TD::OP_Inputs* inputs); 39 | 40 | // Scale 41 | static double evalScale(const TD::OP_Inputs* inputs); 42 | 43 | // Apply Offset 44 | static bool evalApplyoffset(const TD::OP_Inputs* inputs); 45 | 46 | // Offset 47 | static double evalOffset(const TD::OP_Inputs* inputs); 48 | 49 | 50 | }; 51 | #pragma endregion -------------------------------------------------------------------------------- /CHOP/BasicFilterCHOP/README.md: -------------------------------------------------------------------------------- 1 | # Basic Filter CHOP 2 | 3 | The Basic Filter CHOP is a barebones example of a custom CHOP operator. It takes it input and optionaly applies a multiplier and offset to the input values. 4 | 5 | ## Parameters 6 | * **Apply Scale** - When enabled the input values are multiplied by the `Scale` parameter. 7 | * **Scale** - The value the input is multiplied by. 8 | * **Apply Offset** - When enabled the `Offset` parameter is added to the input values. 9 | * **Offset** - The value added to the input values. 10 | -------------------------------------------------------------------------------- /CHOP/BasicGeneratorCHOP/BasicGeneratorCHOP.h: -------------------------------------------------------------------------------- 1 | /* Shared Use License: This file is owned by Derivative Inc. (Derivative) 2 | * and can only be used, and/or modified for use, in conjunction with 3 | * Derivative's TouchDesigner software, and only if you are a licensee who has 4 | * accepted Derivative's TouchDesigner license or assignment agreement 5 | * (which also govern the use of this file). You may share or redistribute 6 | * a modified version of this file provided the following conditions are met: 7 | * 8 | * 1. The shared file or redistribution must retain the information set out 9 | * above and this list of conditions. 10 | * 2. Derivative's name (Derivative Inc.) or its trademarks may not be used 11 | * to endorse or promote products derived from this file without specific 12 | * prior written permission from Derivative. 13 | */ 14 | 15 | #ifndef __BasicGeneratorCHOP__ 16 | #define __BasicGeneratorCHOP__ 17 | 18 | #include "CHOP_CPlusPlusBase.h" 19 | #include "Parameters.h" 20 | 21 | using namespace TD; 22 | 23 | /* 24 | This example implements a CHOP which takes the following parameters: 25 | - Length: The number of samples produced per channel. 26 | - Number of Channels: The number of channels produced. 27 | - Apply Scale: If On, scale values. 28 | - Scale: A scalar by which the output signal is scaled. 29 | - Operation: One of [Add, Multiply, Power] which controls which operation the output signal constitutes 30 | 31 | The output values are: scale*(channel operation sample) 32 | 33 | This CHOP is a generator so it does not need an input and it is not time sliced. 34 | */ 35 | 36 | // Check methods [getNumInfoCHOPChans, getInfoCHOPChan, getInfoDATSize, getInfoDATEntries] 37 | // if you want to output values to the Info CHOP/DAT 38 | 39 | // To get more help about these functions, look at CHOP_CPlusPlusBase.h 40 | class BasicGeneratorCHOP : public CHOP_CPlusPlusBase 41 | { 42 | public: 43 | BasicGeneratorCHOP(const OP_NodeInfo* info); 44 | virtual ~BasicGeneratorCHOP(); 45 | 46 | virtual void getGeneralInfo(CHOP_GeneralInfo*, const TD::OP_Inputs*, void*) override; 47 | virtual bool getOutputInfo(CHOP_OutputInfo*, const TD::OP_Inputs*, void*) override; 48 | virtual void getChannelName(int32_t index, OP_String *name, const TD::OP_Inputs*, void*) override; 49 | 50 | virtual void execute(CHOP_Output*, const TD::OP_Inputs*, void*) override; 51 | 52 | virtual void setupParameters(TD::OP_ParameterManager* manager, void*) override; 53 | 54 | private: 55 | 56 | Parameters myParms; 57 | }; 58 | 59 | #endif 60 | -------------------------------------------------------------------------------- /CHOP/BasicGeneratorCHOP/BasicGeneratorCHOP.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio 14 4 | VisualStudioVersion = 14.0.25420.1 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "BasicGeneratorCHOP", "BasicGeneratorCHOP.vcxproj", "{3F5BEECD-FA36-459F-91B8-BB481A67EF44}" 7 | EndProject 8 | Global 9 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 10 | Debug|x64 = Debug|x64 11 | Release|x64 = Release|x64 12 | EndGlobalSection 13 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 14 | {3F5BEECD-FA36-459F-91B8-BB481A67EF44}.Debug|x64.ActiveCfg = Debug|x64 15 | {3F5BEECD-FA36-459F-91B8-BB481A67EF44}.Debug|x64.Build.0 = Debug|x64 16 | {3F5BEECD-FA36-459F-91B8-BB481A67EF44}.Release|x64.ActiveCfg = Release|x64 17 | {3F5BEECD-FA36-459F-91B8-BB481A67EF44}.Release|x64.Build.0 = Release|x64 18 | EndGlobalSection 19 | GlobalSection(SolutionProperties) = preSolution 20 | HideSolutionNode = FALSE 21 | EndGlobalSection 22 | EndGlobal 23 | -------------------------------------------------------------------------------- /CHOP/BasicGeneratorCHOP/Parameters.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include "CPlusPlus_Common.h" 4 | #include "Parameters.h" 5 | 6 | #pragma region Evals 7 | 8 | int 9 | Parameters::evalLength(const TD::OP_Inputs* inputs) 10 | { 11 | return inputs->getParInt(LengthName); 12 | } 13 | 14 | int 15 | Parameters::evalNumberofchannels(const TD::OP_Inputs* inputs) 16 | { 17 | return inputs->getParInt(NumberofchannelsName); 18 | } 19 | 20 | bool 21 | Parameters::evalApplyscale(const TD::OP_Inputs* inputs) 22 | { 23 | return inputs->getParInt(ApplyscaleName) ? true : false; 24 | } 25 | 26 | double 27 | Parameters::evalScale(const TD::OP_Inputs* inputs) 28 | { 29 | return inputs->getParDouble(ScaleName); 30 | } 31 | 32 | OperationMenuItems 33 | Parameters::evalOperation(const TD::OP_Inputs* inputs) 34 | { 35 | return static_cast(inputs->getParInt(OperationName)); 36 | } 37 | 38 | 39 | #pragma endregion 40 | 41 | #pragma region Setup 42 | 43 | void 44 | Parameters::setup(TD::OP_ParameterManager* manager) 45 | { 46 | { 47 | TD::OP_NumericParameter p; 48 | p.name = LengthName; 49 | p.label = LengthLabel; 50 | p.page = "Generator Basic"; 51 | p.defaultValues[0] = 10; 52 | p.minSliders[0] = 1.0; 53 | p.maxSliders[0] = 50.0; 54 | p.minValues[0] = 1.0; 55 | p.maxValues[0] = 1.0; 56 | p.clampMins[0] = true; 57 | p.clampMaxes[0] = false; 58 | TD::OP_ParAppendResult res = manager->appendInt(p); 59 | 60 | assert(res == TD::OP_ParAppendResult::Success); 61 | } 62 | 63 | { 64 | TD::OP_NumericParameter p; 65 | p.name = NumberofchannelsName; 66 | p.label = NumberofchannelsLabel; 67 | p.page = "Generator Basic"; 68 | p.defaultValues[0] = 10; 69 | p.minSliders[0] = 0.0; 70 | p.maxSliders[0] = 50.0; 71 | p.minValues[0] = 0.0; 72 | p.maxValues[0] = 1.0; 73 | p.clampMins[0] = false; 74 | p.clampMaxes[0] = false; 75 | TD::OP_ParAppendResult res = manager->appendInt(p); 76 | 77 | assert(res == TD::OP_ParAppendResult::Success); 78 | } 79 | 80 | { 81 | TD::OP_NumericParameter p; 82 | p.name = ApplyscaleName; 83 | p.label = ApplyscaleLabel; 84 | p.page = "Generator Basic"; 85 | p.defaultValues[0] = false; 86 | 87 | TD::OP_ParAppendResult res = manager->appendToggle(p); 88 | 89 | assert(res == TD::OP_ParAppendResult::Success); 90 | } 91 | 92 | { 93 | TD::OP_NumericParameter p; 94 | p.name = ScaleName; 95 | p.label = ScaleLabel; 96 | p.page = "Generator Basic"; 97 | p.defaultValues[0] = 1.0; 98 | p.minSliders[0] = -10.0; 99 | p.maxSliders[0] = 10.0; 100 | p.minValues[0] = 0.0; 101 | p.maxValues[0] = 1.0; 102 | p.clampMins[0] = false; 103 | p.clampMaxes[0] = false; 104 | TD::OP_ParAppendResult res = manager->appendFloat(p); 105 | 106 | assert(res == TD::OP_ParAppendResult::Success); 107 | } 108 | 109 | { 110 | TD::OP_StringParameter p; 111 | p.name = OperationName; 112 | p.label = OperationLabel; 113 | p.page = "Generator Basic"; 114 | p.defaultValue = "Add"; 115 | std::array Names = 116 | { 117 | "Add", 118 | "Multiply", 119 | "Power" 120 | }; 121 | std::array Labels = 122 | { 123 | "Add", 124 | "Multiply", 125 | "Power" 126 | }; 127 | TD::OP_ParAppendResult res = manager->appendMenu(p, Names.size(), Names.data(), Labels.data()); 128 | 129 | assert(res == TD::OP_ParAppendResult::Success); 130 | } 131 | 132 | 133 | } 134 | 135 | #pragma endregion -------------------------------------------------------------------------------- /CHOP/BasicGeneratorCHOP/Parameters.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | class TD::OP_Inputs; 6 | class TD::OP_ParameterManager; 7 | 8 | #pragma region ParNames and ParLabels 9 | 10 | // Names of the parameters 11 | 12 | constexpr static char LengthName[] = "Length"; 13 | constexpr static char LengthLabel[] = "Length"; 14 | 15 | constexpr static char NumberofchannelsName[] = "Numberofchannels"; 16 | constexpr static char NumberofchannelsLabel[] = "Number Of Channels"; 17 | 18 | constexpr static char ApplyscaleName[] = "Applyscale"; 19 | constexpr static char ApplyscaleLabel[] = "Apply Scale"; 20 | 21 | constexpr static char ScaleName[] = "Scale"; 22 | constexpr static char ScaleLabel[] = "Scale"; 23 | 24 | constexpr static char OperationName[] = "Operation"; 25 | constexpr static char OperationLabel[] = "Operation"; 26 | 27 | 28 | #pragma endregion 29 | 30 | #pragma region Menus 31 | enum class OperationMenuItems 32 | { 33 | Add, 34 | Multiply, 35 | Power 36 | }; 37 | 38 | #pragma endregion 39 | 40 | 41 | #pragma region Parameters 42 | class Parameters 43 | { 44 | public: 45 | static void setup(TD::OP_ParameterManager*); 46 | 47 | // Length 48 | static int evalLength(const TD::OP_Inputs* inputs); 49 | 50 | // Number Of Channels 51 | static int evalNumberofchannels(const TD::OP_Inputs* inputs); 52 | 53 | // Apply Scale 54 | static bool evalApplyscale(const TD::OP_Inputs* inputs); 55 | 56 | // Scale 57 | static double evalScale(const TD::OP_Inputs* inputs); 58 | 59 | // Operation 60 | static OperationMenuItems evalOperation(const TD::OP_Inputs* inputs); 61 | 62 | 63 | }; 64 | #pragma endregion -------------------------------------------------------------------------------- /CHOP/BasicGeneratorCHOP/README.md: -------------------------------------------------------------------------------- 1 | # Basic Generator CHOP 2 | 3 | The Basic Generator CHOP is a barebones example for creating a custom CHOP generator. The example creates a number of channels with certain length. 4 | The channel values are acted upon depended by the operation choosen and their index. For example with the operation `Add` the first channel has 0 added (the first channel's index is 0) while the second channel has 1 added (the second channel's index is 1). 5 | 6 | ## Parameters 7 | * **Length** - The number of samples in the operator. 8 | * **Number of Channeles** - The number of channels created by the operator. 9 | * **Apply Scale** - When enabled, the channel values are multiplied by the value of the `Scale` parameter. 10 | * **Scale** - The value the channels are multiplied by. 11 | * **Operation** - The Operation that is done on the created channels depending on their channel index. 12 | * **Add** - Each channel has its index added to it. 13 | * **Multiply** - Each channel is multiplied by its index. 14 | * **Power** - Each channel is taken to the power of its index. 15 | -------------------------------------------------------------------------------- /CHOP/OneEuroCHOP/OneEuroCHOP.h: -------------------------------------------------------------------------------- 1 | /* Shared Use License: This file is owned by Derivative Inc. (Derivative) 2 | * and can only be used, and/or modified for use, in conjunction with 3 | * Derivative's TouchDesigner software, and only if you are a licensee who has 4 | * accepted Derivative's TouchDesigner license or assignment agreement 5 | * (which also govern the use of this file). You may share or redistribute 6 | * a modified version of this file provided the following conditions are met: 7 | * 8 | * 1. The shared file or redistribution must retain the information set out 9 | * above and this list of conditions. 10 | * 2. Derivative's name (Derivative Inc.) or its trademarks may not be used 11 | * to endorse or promote products derived from this file without specific 12 | * prior written permission from Derivative. 13 | */ 14 | #ifndef __OneEuroCHOP__ 15 | #define __OneEuroCHOP__ 16 | 17 | #include "CHOP_CPlusPlusBase.h" 18 | #include "Parameters.h" 19 | #include 20 | 21 | class OneEuroImpl; 22 | 23 | using namespace TD; 24 | 25 | /* 26 | This example implements a CHOP that filters noice out of a signl. 27 | It takes the following parameters: 28 | - Cutoff Frequency (Hz): Decrease it if slow speed jitter is a problem. 29 | - Speed Coefficient: Increase if high speed lag is a problem. 30 | - Slope Cutoff Frequency (Hz): Avoids high derivative bursts caused by jitter. 31 | 32 | References: 33 | - Casiez, G., Roussel, N. and Vogel, D. (2012). 1€ Filter: A Simple 34 | Speed-based Low-pass Filter for Noisy Input in Interactive Systems. 35 | Proceedings of the ACM Conference on Human Factors in Computing Systems 36 | (CHI '12). Austin, Texas (May 5-12, 2012). New York: ACM Press, pp. 2527-2530. 37 | 38 | For more information about tuning the parameters check the paper mentioned. 39 | This CHOP is a filter and it takes exactly one input. 40 | */ 41 | 42 | // Check methods [getNumInfoCHOPChans, getInfoCHOPChan, getInfoDATSize, getInfoDATEntries] 43 | // if you want to output values to the Info CHOP/DAT 44 | 45 | // To get more help about these functions, look at CHOP_CPlusPlusBase.h 46 | class OneEuroCHOP : public CHOP_CPlusPlusBase 47 | { 48 | public: 49 | OneEuroCHOP(const OP_NodeInfo* info); 50 | virtual ~OneEuroCHOP(); 51 | 52 | virtual void getGeneralInfo(CHOP_GeneralInfo*, const TD::OP_Inputs*, void*) override; 53 | virtual bool getOutputInfo(CHOP_OutputInfo*, const TD::OP_Inputs*, void*) override; 54 | virtual void getChannelName(int32_t index, OP_String *name, const TD::OP_Inputs*, void*) override; 55 | 56 | virtual void execute(CHOP_Output*, const TD::OP_Inputs*, void*) override; 57 | 58 | virtual void setupParameters(TD::OP_ParameterManager* manager, void*) override; 59 | 60 | 61 | private: 62 | void handleParameters(const TD::OP_Inputs*, const OP_CHOPInput*); 63 | 64 | std::vector myFiltersPerChannel; 65 | Parameters myParms; 66 | }; 67 | 68 | #endif 69 | -------------------------------------------------------------------------------- /CHOP/OneEuroCHOP/OneEuroCHOP.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio Version 16 4 | VisualStudioVersion = 16.0.30011.22 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "OneEuroCHOP", "OneEuroCHOP.vcxproj", "{3F5BEECD-FA36-459F-91B8-BB481A67EF44}" 7 | EndProject 8 | Global 9 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 10 | Debug|x64 = Debug|x64 11 | Release|x64 = Release|x64 12 | EndGlobalSection 13 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 14 | {3F5BEECD-FA36-459F-91B8-BB481A67EF44}.Debug|x64.ActiveCfg = Debug|x64 15 | {3F5BEECD-FA36-459F-91B8-BB481A67EF44}.Debug|x64.Build.0 = Debug|x64 16 | {3F5BEECD-FA36-459F-91B8-BB481A67EF44}.Release|x64.ActiveCfg = Release|x64 17 | {3F5BEECD-FA36-459F-91B8-BB481A67EF44}.Release|x64.Build.0 = Release|x64 18 | EndGlobalSection 19 | GlobalSection(SolutionProperties) = preSolution 20 | HideSolutionNode = FALSE 21 | EndGlobalSection 22 | GlobalSection(ExtensibilityGlobals) = postSolution 23 | SolutionGuid = {CDCA304D-7173-47CC-BC43-257E4444266C} 24 | EndGlobalSection 25 | EndGlobal 26 | -------------------------------------------------------------------------------- /CHOP/OneEuroCHOP/OneEuroImpl.cpp: -------------------------------------------------------------------------------- 1 | #include "OneEuroImpl.h" 2 | #include 3 | 4 | static constexpr double PI = 3.141592653589793238463; 5 | 6 | class LowPassFilter 7 | { 8 | public: 9 | LowPassFilter() : 10 | myFirstFiltering{ true }, myHatXPrev{}, myHatX{} 11 | { 12 | 13 | } 14 | 15 | virtual ~LowPassFilter() 16 | { 17 | 18 | } 19 | 20 | double 21 | filter(double value, double alpha) 22 | { 23 | if (myFirstFiltering) 24 | { 25 | myFirstFiltering = false; 26 | myHatXPrev = value; 27 | } 28 | myHatX = alpha * value + (1.0 - alpha) * myHatXPrev; 29 | myHatXPrev = myHatX; 30 | return myHatX; 31 | } 32 | 33 | double 34 | getHatXPrev() 35 | { 36 | return myHatXPrev; 37 | } 38 | 39 | private: 40 | bool myFirstFiltering; 41 | 42 | double myHatXPrev; 43 | double myHatX; 44 | }; 45 | 46 | OneEuroImpl::OneEuroImpl( 47 | double rate, double minCutOff, double beta, double dCutOff 48 | ) : 49 | myFirstFiltering{true}, myRate{rate}, myMinCutOff{minCutOff}, 50 | myBeta{beta}, myXFilt{new LowPassFilter()}, myDCutOff{dCutOff}, 51 | myDxFilt{new LowPassFilter()} 52 | { 53 | 54 | } 55 | 56 | OneEuroImpl::~OneEuroImpl() 57 | { 58 | delete myXFilt; 59 | delete myDxFilt; 60 | } 61 | 62 | void 63 | OneEuroImpl::changeInput(double rate, double minCutOff, double beta, double dCutOff) 64 | { 65 | myRate = rate; 66 | myMinCutOff = minCutOff; 67 | myBeta = beta; 68 | myDCutOff = dCutOff; 69 | } 70 | 71 | double 72 | OneEuroImpl::filter(double x) 73 | { 74 | double dx = myFirstFiltering ? 0.0 : (x - myXFilt->getHatXPrev()) * myRate; 75 | myFirstFiltering = false; 76 | double edx = myDxFilt->filter(dx, alpha(myDCutOff)); 77 | double cutOff = myMinCutOff + myBeta * std::abs(edx); 78 | return myXFilt->filter(x, alpha(cutOff)); 79 | } 80 | 81 | double 82 | OneEuroImpl::alpha(double cutoff) 83 | { 84 | double tau = 1.0 / (2 * PI * cutoff); 85 | double te = 1.0 / myRate; 86 | return 1.0 / (1.0 + tau/te); 87 | } 88 | -------------------------------------------------------------------------------- /CHOP/OneEuroCHOP/OneEuroImpl.h: -------------------------------------------------------------------------------- 1 | /* Shared Use License: This file is owned by Derivative Inc. (Derivative) 2 | * and can only be used, and/or modified for use, in conjunction with 3 | * Derivative's TouchDesigner software, and only if you are a licensee who has 4 | * accepted Derivative's TouchDesigner license or assignment agreement 5 | * (which also govern the use of this file). You may share or redistribute 6 | * a modified version of this file provided the following conditions are met: 7 | * 8 | * 1. The shared file or redistribution must retain the information set out 9 | * above and this list of conditions. 10 | * 2. Derivative's name (Derivative Inc.) or its trademarks may not be used 11 | * to endorse or promote products derived from this file without specific 12 | * prior written permission from Derivative. 13 | */ 14 | #ifndef __OneEuroImpl__ 15 | #define __OneEuroImpl__ 16 | 17 | class LowPassFilter; 18 | 19 | /* 20 | Implementation of the 1€ Filter described in the paper: 21 | - Casiez, G., Roussel, N. and Vogel, D. (2012). 1€ Filter: A Simple 22 | Speed-based Low-pass Filter for Noisy Input in Interactive Systems. 23 | Proceedings of the ACM Conference on Human Factors in Computing Systems 24 | (CHI '12). Austin, Texas (May 5-12, 2012). New York: ACM Press, pp. 2527-2530. 25 | */ 26 | 27 | class OneEuroImpl 28 | { 29 | public: 30 | OneEuroImpl(double rate, double minCutOff, double beta, double dCutOff); 31 | virtual ~OneEuroImpl(); 32 | 33 | void changeInput(double rate, double minCutOff, double beta, double dCutOff); 34 | 35 | double filter(double value); 36 | 37 | double alpha(double cutOff); 38 | 39 | private: 40 | bool myFirstFiltering; 41 | double myRate; 42 | double myMinCutOff; 43 | double myBeta; 44 | LowPassFilter* myXFilt; 45 | double myDCutOff; 46 | LowPassFilter* myDxFilt; 47 | }; 48 | #endif 49 | -------------------------------------------------------------------------------- /CHOP/OneEuroCHOP/Parameters.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include "CPlusPlus_Common.h" 4 | #include "Parameters.h" 5 | 6 | #pragma region Evals 7 | 8 | double 9 | Parameters::evalMincutoff(const TD::OP_Inputs* inputs) 10 | { 11 | return inputs->getParDouble(MincutoffName); 12 | } 13 | 14 | double 15 | Parameters::evalBeta(const TD::OP_Inputs* inputs) 16 | { 17 | return inputs->getParDouble(BetaName); 18 | } 19 | 20 | double 21 | Parameters::evalDcutoff(const TD::OP_Inputs* inputs) 22 | { 23 | return inputs->getParDouble(DcutoffName); 24 | } 25 | 26 | 27 | #pragma endregion 28 | 29 | #pragma region Setup 30 | 31 | void 32 | Parameters::setup(TD::OP_ParameterManager* manager) 33 | { 34 | { 35 | TD::OP_NumericParameter p; 36 | p.name = MincutoffName; 37 | p.label = MincutoffLabel; 38 | p.page = "Filter"; 39 | p.defaultValues[0] = 1.0; 40 | p.minSliders[0] = 0.0; 41 | p.maxSliders[0] = 10.0; 42 | p.minValues[0] = 0.0; 43 | p.maxValues[0] = 1.0; 44 | p.clampMins[0] = false; 45 | p.clampMaxes[0] = false; 46 | TD::OP_ParAppendResult res = manager->appendFloat(p); 47 | 48 | assert(res == TD::OP_ParAppendResult::Success); 49 | } 50 | 51 | { 52 | TD::OP_NumericParameter p; 53 | p.name = BetaName; 54 | p.label = BetaLabel; 55 | p.page = "Filter"; 56 | p.defaultValues[0] = 0.0; 57 | p.minSliders[0] = 0.0; 58 | p.maxSliders[0] = 1.0; 59 | p.minValues[0] = 0.0; 60 | p.maxValues[0] = 1.0; 61 | p.clampMins[0] = false; 62 | p.clampMaxes[0] = false; 63 | TD::OP_ParAppendResult res = manager->appendFloat(p); 64 | 65 | assert(res == TD::OP_ParAppendResult::Success); 66 | } 67 | 68 | { 69 | TD::OP_NumericParameter p; 70 | p.name = DcutoffName; 71 | p.label = DcutoffLabel; 72 | p.page = "Filter"; 73 | p.defaultValues[0] = 1.0; 74 | p.minSliders[0] = 0.0; 75 | p.maxSliders[0] = 10.0; 76 | p.minValues[0] = 0.0; 77 | p.maxValues[0] = 1.0; 78 | p.clampMins[0] = false; 79 | p.clampMaxes[0] = false; 80 | TD::OP_ParAppendResult res = manager->appendFloat(p); 81 | 82 | assert(res == TD::OP_ParAppendResult::Success); 83 | } 84 | 85 | 86 | } 87 | 88 | #pragma endregion -------------------------------------------------------------------------------- /CHOP/OneEuroCHOP/Parameters.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | class TD::OP_Inputs; 6 | class TD::OP_ParameterManager; 7 | 8 | #pragma region ParNames and ParLabels 9 | 10 | // Names of the parameters 11 | 12 | constexpr static char MincutoffName[] = "Mincutoff"; 13 | constexpr static char MincutoffLabel[] = "Cutoff Frequency(Hz)"; 14 | 15 | constexpr static char BetaName[] = "Beta"; 16 | constexpr static char BetaLabel[] = "Speed Coefficient"; 17 | 18 | constexpr static char DcutoffName[] = "Dcutoff"; 19 | constexpr static char DcutoffLabel[] = "Slope Cutoff Frequency (Hz)"; 20 | 21 | 22 | #pragma endregion 23 | 24 | #pragma region Menus 25 | #pragma endregion 26 | 27 | 28 | #pragma region Parameters 29 | class Parameters 30 | { 31 | public: 32 | static void setup(TD::OP_ParameterManager*); 33 | 34 | // Cutoff Frequency(Hz) 35 | static double evalMincutoff(const TD::OP_Inputs* inputs); 36 | 37 | // Speed Coefficient 38 | static double evalBeta(const TD::OP_Inputs* inputs); 39 | 40 | // Slope Cutoff Frequency (Hz) 41 | static double evalDcutoff(const TD::OP_Inputs* inputs); 42 | 43 | 44 | }; 45 | #pragma endregion -------------------------------------------------------------------------------- /CHOP/OneEuroCHOP/README.md: -------------------------------------------------------------------------------- 1 | # One Euro CHOP 2 | 3 | The One Euro CHOP implements the One Euro Filter as described here: http://cristal.univ-lille.fr/~casiez/1euro/ 4 | After initially making this custom operator, the functionality was also included into the build in [Filter CHOP](https://docs.derivative.ca/Filter_CHOP). 5 | The one Euro Filter is especially useful when a person is in an interaction loop with TouchDesigner and wants quick response: It responds quickly to large changes in value, and it smooths out jitters in the input. 6 | 7 | ## Parameters 8 | * **Cutoff Frequency (Hz)** - Decrease it if slow speed jitter is a problem. 9 | * **Speed Coefficient** - Avoids high derivative bursts caused by jitter. (The research paper implementation fixes this value to 1Hz but defaults to ) 10 | * **Slope Cutoff Frequency (Hz)** - Increase if high speed lag is a problem. 11 | -------------------------------------------------------------------------------- /CHOP/TimeSliceFilterCHOP/GL_Extensions.h: -------------------------------------------------------------------------------- 1 | // Stub file for simpler CHOP usage than an OpenGLTOP 2 | 3 | #include 4 | -------------------------------------------------------------------------------- /CHOP/TimeSliceFilterCHOP/Parameters.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include "CPlusPlus_Common.h" 4 | #include "Parameters.h" 5 | 6 | #pragma region Evals 7 | 8 | OperationMenuItems 9 | Parameters::evalOperation(const TD::OP_Inputs* inputs) 10 | { 11 | return static_cast(inputs->getParInt(OperationName)); 12 | } 13 | 14 | int 15 | Parameters::evalReset(const TD::OP_Inputs* inputs) 16 | { 17 | return inputs->getParInt(ResetName); 18 | } 19 | 20 | 21 | #pragma endregion 22 | 23 | #pragma region Setup 24 | 25 | void 26 | Parameters::setup(TD::OP_ParameterManager* manager) 27 | { 28 | { 29 | TD::OP_StringParameter p; 30 | p.name = OperationName; 31 | p.label = OperationLabel; 32 | p.page = "Filter"; 33 | p.defaultValue = "Max"; 34 | std::array Names = 35 | { 36 | "Max", 37 | "Min", 38 | "Average" 39 | }; 40 | std::array Labels = 41 | { 42 | "Max", 43 | "Min", 44 | "Average" 45 | }; 46 | TD::OP_ParAppendResult res = manager->appendMenu(p, Names.size(), Names.data(), Labels.data()); 47 | 48 | assert(res == TD::OP_ParAppendResult::Success); 49 | } 50 | 51 | { 52 | TD::OP_NumericParameter p; 53 | p.name = ResetName; 54 | p.label = ResetLabel; 55 | p.page = "Filter"; 56 | TD::OP_ParAppendResult res = manager->appendPulse(p); 57 | 58 | assert(res == TD::OP_ParAppendResult::Success); 59 | } 60 | 61 | 62 | } 63 | 64 | #pragma endregion -------------------------------------------------------------------------------- /CHOP/TimeSliceFilterCHOP/Parameters.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | class TD::OP_Inputs; 6 | class TD::OP_ParameterManager; 7 | 8 | #pragma region ParNames and ParLabels 9 | 10 | // Names of the parameters 11 | 12 | constexpr static char OperationName[] = "Operation"; 13 | constexpr static char OperationLabel[] = "Operation"; 14 | 15 | constexpr static char ResetName[] = "Reset"; 16 | constexpr static char ResetLabel[] = "Reset"; 17 | 18 | 19 | #pragma endregion 20 | 21 | #pragma region Menus 22 | enum class OperationMenuItems 23 | { 24 | Max, 25 | Min, 26 | Average 27 | }; 28 | 29 | #pragma endregion 30 | 31 | 32 | #pragma region Parameters 33 | class Parameters 34 | { 35 | public: 36 | static void setup(TD::OP_ParameterManager*); 37 | 38 | // Operation 39 | static OperationMenuItems evalOperation(const TD::OP_Inputs* inputs); 40 | 41 | // Reset 42 | static int evalReset(const TD::OP_Inputs* inputs); 43 | 44 | 45 | }; 46 | #pragma endregion -------------------------------------------------------------------------------- /CHOP/TimeSliceFilterCHOP/README.md: -------------------------------------------------------------------------------- 1 | # Timeslice Filter CHOP 2 | This is a bare bones example for creating a timesliced filter CHOP. It looks at its input and displays the Minimum, Maximum or Average of all previous values. 3 | 4 | ## Parameters 5 | * **Operation** - The operation of the operator. 6 | * **Max** - Display the maximum of all previous values. 7 | * **Min** - Display the minimum of all previous values. 8 | * **Average** - Display the average of all previous values. 9 | * **Reset** - Reset the CHOP. 10 | -------------------------------------------------------------------------------- /CHOP/TimeSliceFilterCHOP/TimeSliceFilterCHOP.h: -------------------------------------------------------------------------------- 1 | /* Shared Use License: This file is owned by Derivative Inc. (Derivative) 2 | * and can only be used, and/or modified for use, in conjunction with 3 | * Derivative's TouchDesigner software, and only if you are a licensee who has 4 | * accepted Derivative's TouchDesigner license or assignment agreement 5 | * (which also govern the use of this file). You may share or redistribute 6 | * a modified version of this file provided the following conditions are met: 7 | * 8 | * 1. The shared file or redistribution must retain the information set out 9 | * above and this list of conditions. 10 | * 2. Derivative's name (Derivative Inc.) or its trademarks may not be used 11 | * to endorse or promote products derived from this file without specific 12 | * prior written permission from Derivative. 13 | */ 14 | 15 | #ifndef __TimeSliceFilterCHOP__ 16 | #define __TimeSliceFilterCHOP__ 17 | 18 | #include "CHOP_CPlusPlusBase.h" 19 | #include "Parameters.h" 20 | #include 21 | 22 | class FilterValues; 23 | 24 | using namespace TD; 25 | 26 | /* 27 | This example implements a CHOP which takes the following parameters: 28 | - Operation: One of [Max, Min, Average] which controls which operation is applied to 29 | the input signal. 30 | - Reset: A pulse to reset the signal. 31 | 32 | This CHOP is a filter and it takes at least one input. 33 | 34 | The output signal is: the current maximum, minimum, or average value of the input signal 35 | */ 36 | 37 | // Check methods [getNumInfoCHOPChans, getInfoCHOPChan, getInfoDATSize, getInfoDATEntries] 38 | // if you want to output values to the Info CHOP/DAT 39 | 40 | // To get more help about these functions, look at CHOP_CPlusPlusBase.h 41 | class TimeSliceFilterCHOP : public CHOP_CPlusPlusBase 42 | { 43 | public: 44 | TimeSliceFilterCHOP(const OP_NodeInfo* info); 45 | virtual ~TimeSliceFilterCHOP(); 46 | 47 | virtual void getGeneralInfo(CHOP_GeneralInfo*, const TD::OP_Inputs*, void*) override; 48 | virtual bool getOutputInfo(CHOP_OutputInfo*, const TD::OP_Inputs*, void*) override; 49 | virtual void getChannelName(int32_t index, OP_String *name, const TD::OP_Inputs*, void*) override; 50 | 51 | virtual void execute(CHOP_Output*, const TD::OP_Inputs*, void*) override; 52 | 53 | virtual void setupParameters(TD::OP_ParameterManager* manager, void*) override; 54 | virtual void pulsePressed(const char* name, void* reserved1) override; 55 | 56 | private: 57 | std::vector myValues; 58 | Parameters myParms; 59 | }; 60 | 61 | #endif 62 | -------------------------------------------------------------------------------- /CHOP/TimeSliceFilterCHOP/TimeSliceFilterCHOP.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio Version 16 4 | VisualStudioVersion = 16.0.30011.22 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "TimeSliceFilterCHOP", "TimeSliceFilterCHOP.vcxproj", "{3F5BEECD-FA36-459F-91B8-BB481A67EF44}" 7 | EndProject 8 | Global 9 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 10 | Debug|x64 = Debug|x64 11 | Release|x64 = Release|x64 12 | EndGlobalSection 13 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 14 | {3F5BEECD-FA36-459F-91B8-BB481A67EF44}.Debug|x64.ActiveCfg = Debug|x64 15 | {3F5BEECD-FA36-459F-91B8-BB481A67EF44}.Debug|x64.Build.0 = Debug|x64 16 | {3F5BEECD-FA36-459F-91B8-BB481A67EF44}.Release|x64.ActiveCfg = Release|x64 17 | {3F5BEECD-FA36-459F-91B8-BB481A67EF44}.Release|x64.Build.0 = Release|x64 18 | EndGlobalSection 19 | GlobalSection(SolutionProperties) = preSolution 20 | HideSolutionNode = FALSE 21 | EndGlobalSection 22 | GlobalSection(ExtensibilityGlobals) = postSolution 23 | SolutionGuid = {CDCA304D-7173-47CC-BC43-257E4444266C} 24 | EndGlobalSection 25 | EndGlobal 26 | -------------------------------------------------------------------------------- /CHOP/TimeSliceGeneratorCHOP/Parameters.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include "CPlusPlus_Common.h" 4 | #include "Parameters.h" 5 | 6 | #pragma region Evals 7 | 8 | TypeMenuItems 9 | Parameters::evalType(const TD::OP_Inputs* inputs) 10 | { 11 | return static_cast(inputs->getParInt(TypeName)); 12 | } 13 | 14 | double 15 | Parameters::evalFrequency(const TD::OP_Inputs* inputs) 16 | { 17 | return inputs->getParDouble(FrequencyName); 18 | } 19 | 20 | bool 21 | Parameters::evalApplyscale(const TD::OP_Inputs* inputs) 22 | { 23 | return inputs->getParInt(ApplyscaleName) ? true : false; 24 | } 25 | 26 | double 27 | Parameters::evalScale(const TD::OP_Inputs* inputs) 28 | { 29 | return inputs->getParDouble(ScaleName); 30 | } 31 | 32 | 33 | #pragma endregion 34 | 35 | #pragma region Setup 36 | 37 | void 38 | Parameters::setup(TD::OP_ParameterManager* manager) 39 | { 40 | { 41 | TD::OP_StringParameter p; 42 | p.name = TypeName; 43 | p.label = TypeLabel; 44 | p.page = "Generator"; 45 | p.defaultValue = "Sine"; 46 | std::array Names = 47 | { 48 | "Sine", 49 | "Square", 50 | "Ramp" 51 | }; 52 | std::array Labels = 53 | { 54 | "Sine", 55 | "Square", 56 | "Ramp" 57 | }; 58 | TD::OP_ParAppendResult res = manager->appendMenu(p, Names.size(), Names.data(), Labels.data()); 59 | 60 | assert(res == TD::OP_ParAppendResult::Success); 61 | } 62 | 63 | { 64 | TD::OP_NumericParameter p; 65 | p.name = FrequencyName; 66 | p.label = FrequencyLabel; 67 | p.page = "Generator"; 68 | p.defaultValues[0] = 1.0; 69 | p.minSliders[0] = -10.0; 70 | p.maxSliders[0] = 10.0; 71 | p.minValues[0] = 0.0; 72 | p.maxValues[0] = 1.0; 73 | p.clampMins[0] = false; 74 | p.clampMaxes[0] = false; 75 | TD::OP_ParAppendResult res = manager->appendFloat(p); 76 | 77 | assert(res == TD::OP_ParAppendResult::Success); 78 | } 79 | 80 | { 81 | TD::OP_NumericParameter p; 82 | p.name = ApplyscaleName; 83 | p.label = ApplyscaleLabel; 84 | p.page = "Generator"; 85 | p.defaultValues[0] = false; 86 | 87 | TD::OP_ParAppendResult res = manager->appendToggle(p); 88 | 89 | assert(res == TD::OP_ParAppendResult::Success); 90 | } 91 | 92 | { 93 | TD::OP_NumericParameter p; 94 | p.name = ScaleName; 95 | p.label = ScaleLabel; 96 | p.page = "Generator"; 97 | p.defaultValues[0] = 1.0; 98 | p.minSliders[0] = -10.0; 99 | p.maxSliders[0] = 10.0; 100 | p.minValues[0] = 0.0; 101 | p.maxValues[0] = 1.0; 102 | p.clampMins[0] = false; 103 | p.clampMaxes[0] = false; 104 | TD::OP_ParAppendResult res = manager->appendFloat(p); 105 | 106 | assert(res == TD::OP_ParAppendResult::Success); 107 | } 108 | 109 | 110 | } 111 | 112 | #pragma endregion -------------------------------------------------------------------------------- /CHOP/TimeSliceGeneratorCHOP/Parameters.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | class TD::OP_Inputs; 6 | class TD::OP_ParameterManager; 7 | 8 | #pragma region ParNames and ParLabels 9 | 10 | // Names of the parameters 11 | 12 | constexpr static char TypeName[] = "Type"; 13 | constexpr static char TypeLabel[] = "Type"; 14 | 15 | constexpr static char FrequencyName[] = "Frequency"; 16 | constexpr static char FrequencyLabel[] = "Frequency"; 17 | 18 | constexpr static char ApplyscaleName[] = "Applyscale"; 19 | constexpr static char ApplyscaleLabel[] = "Apply Scale"; 20 | 21 | constexpr static char ScaleName[] = "Scale"; 22 | constexpr static char ScaleLabel[] = "Scale"; 23 | 24 | 25 | #pragma endregion 26 | 27 | #pragma region Menus 28 | enum class TypeMenuItems 29 | { 30 | Sine, 31 | Square, 32 | Ramp 33 | }; 34 | 35 | #pragma endregion 36 | 37 | 38 | #pragma region Parameters 39 | class Parameters 40 | { 41 | public: 42 | static void setup(TD::OP_ParameterManager*); 43 | 44 | // Type 45 | static TypeMenuItems evalType(const TD::OP_Inputs* inputs); 46 | 47 | // Frequency 48 | static double evalFrequency(const TD::OP_Inputs* inputs); 49 | 50 | // Apply Scale 51 | static bool evalApplyscale(const TD::OP_Inputs* inputs); 52 | 53 | // Scale 54 | static double evalScale(const TD::OP_Inputs* inputs); 55 | 56 | 57 | }; 58 | #pragma endregion -------------------------------------------------------------------------------- /CHOP/TimeSliceGeneratorCHOP/README.md: -------------------------------------------------------------------------------- 1 | # Timeslice Generator CHOP 2 | This is a bare bones example for creating a timesliced generator CHOP. It generates one channel with one sample that is changing over time based on the type of waveform selected with the Type parameter. It is a simpler version of TouchDesigner built-in LFO CHOP. 3 | 4 | ## Parameters 5 | * **Type** - The shape of the waveform to repeat 6 | * **Sine** - (-1 to 1) A Sine wave. 7 | * **Square** - (-1 to 1) Step-up/step-down. 8 | * **Ramp** - (0 to 1) A ramp from 0 to 1. 9 | * **Frequency** - Frequency of the selected curve type. 10 | * **Apply Scale** - Toggle on to have acces to the scale multiplier value below and apply scale to the current value. 11 | * **Scale** - When Apply Scale is toggled on, scale the data by the specified value. 12 | -------------------------------------------------------------------------------- /CHOP/TimeSliceGeneratorCHOP/TimeSliceGeneratorCHOP.h: -------------------------------------------------------------------------------- 1 | /* Shared Use License: This file is owned by Derivative Inc. (Derivative) 2 | * and can only be used, and/or modified for use, in conjunction with 3 | * Derivative's TouchDesigner software, and only if you are a licensee who has 4 | * accepted Derivative's TouchDesigner license or assignment agreement 5 | * (which also govern the use of this file). You may share or redistribute 6 | * a modified version of this file provided the following conditions are met: 7 | * 8 | * 1. The shared file or redistribution must retain the information set out 9 | * above and this list of conditions. 10 | * 2. Derivative's name (Derivative Inc.) or its trademarks may not be used 11 | * to endorse or promote products derived from this file without specific 12 | * prior written permission from Derivative. 13 | */ 14 | 15 | #ifndef __TimeSliceGeneratorCHOP__ 16 | #define __TimeSliceGeneratorCHOP__ 17 | 18 | #include "CHOP_CPlusPlusBase.h" 19 | #include "Parameters.h" 20 | 21 | using namespace TD; 22 | 23 | /* 24 | This example implements a CHOP which takes the following parameters: 25 | - Type: One of [Sine, Square, Ramp] which controls which wave we output. 26 | - Frequency: Determines the frequency of our wave. 27 | - Apply Scale: If On, scale values. 28 | - Scale: A scalar by which the output signal is scaled. 29 | 30 | This CHOP is a generator so it does not need an input. 31 | 32 | The output signal is: scale*(shape value at current time). Note that this CHOP is 33 | time sliced; therefore, we need to keep track of the current time to output the correct 34 | value. 35 | */ 36 | 37 | // Check methods [getNumInfoCHOPChans, getInfoCHOPChan, getInfoDATSize, getInfoDATEntries] 38 | // if you want to output values to the Info CHOP/DAT 39 | 40 | // To get more help about these functions, look at CHOP_CPlusPlusBase.h 41 | class TimeSliceGeneratorCHOP : public CHOP_CPlusPlusBase 42 | { 43 | public: 44 | TimeSliceGeneratorCHOP(const OP_NodeInfo* info); 45 | virtual ~TimeSliceGeneratorCHOP(); 46 | 47 | virtual void getGeneralInfo(CHOP_GeneralInfo*, const TD::OP_Inputs*, void*) override; 48 | virtual bool getOutputInfo(CHOP_OutputInfo*, const TD::OP_Inputs*, void*) override; 49 | virtual void getChannelName(int32_t index, OP_String *name, const TD::OP_Inputs*, void*) override; 50 | 51 | virtual void execute(CHOP_Output*, const TD::OP_Inputs*, void*) override; 52 | 53 | virtual void setupParameters(TD::OP_ParameterManager* manager, void*) override; 54 | 55 | private: 56 | double myOffset; 57 | Parameters myParms; 58 | }; 59 | 60 | #endif 61 | -------------------------------------------------------------------------------- /CHOP/TimeSliceGeneratorCHOP/TimeSliceGeneratorCHOP.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio Version 16 4 | VisualStudioVersion = 16.0.30011.22 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "TimeSliceGeneratorCHOP", "TimeSliceGeneratorCHOP.vcxproj", "{3F5BEECD-FA36-459F-91B8-BB481A67EF44}" 7 | EndProject 8 | Global 9 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 10 | Debug|x64 = Debug|x64 11 | Release|x64 = Release|x64 12 | EndGlobalSection 13 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 14 | {3F5BEECD-FA36-459F-91B8-BB481A67EF44}.Debug|x64.ActiveCfg = Debug|x64 15 | {3F5BEECD-FA36-459F-91B8-BB481A67EF44}.Debug|x64.Build.0 = Debug|x64 16 | {3F5BEECD-FA36-459F-91B8-BB481A67EF44}.Release|x64.ActiveCfg = Release|x64 17 | {3F5BEECD-FA36-459F-91B8-BB481A67EF44}.Release|x64.Build.0 = Release|x64 18 | EndGlobalSection 19 | GlobalSection(SolutionProperties) = preSolution 20 | HideSolutionNode = FALSE 21 | EndGlobalSection 22 | GlobalSection(ExtensibilityGlobals) = postSolution 23 | SolutionGuid = {CDCA304D-7173-47CC-BC43-257E4444266C} 24 | EndGlobalSection 25 | EndGlobal 26 | -------------------------------------------------------------------------------- /DAT/FilterDAT/FilterDAT.h: -------------------------------------------------------------------------------- 1 | /* Shared Use License: This file is owned by Derivative Inc. (Derivative) 2 | * and can only be used, and/or modified for use, in conjunction with 3 | * Derivative's TouchDesigner software, and only if you are a licensee who has 4 | * accepted Derivative's TouchDesigner license or assignment agreement 5 | * (which also govern the use of this file). You may share or redistribute 6 | * a modified version of this file provided the following conditions are met: 7 | * 8 | * 1. The shared file or redistribution must retain the information set out 9 | * above and this list of conditions. 10 | * 2. Derivative's name (Derivative Inc.) or its trademarks may not be used 11 | * to endorse or promote products derived from this file without specific 12 | * prior written permission from Derivative. 13 | */ 14 | 15 | #ifndef __FilterDAT__ 16 | #define __FilterDAT__ 17 | 18 | #include "DAT_CPlusPlusBase.h" 19 | #include "Parameters.h" 20 | 21 | using namespace TD; 22 | /* 23 | This example implements a DAT that takes one input and changes the content's case. 24 | 25 | It takes the following parameters: 26 | - Case: One of [Upper Camel Case, Lower Case, Upper Case]. Which determines how the 27 | content's case changes. 28 | - Keep Spaces: If On, the output will have white space. 29 | */ 30 | 31 | // Check methods [getNumInfoCHOPChans, getInfoCHOPChan, getInfoDATSize, getInfoDATEntries] 32 | // if you want to output values to the Info CHOP/DAT 33 | 34 | // To get more help about these functions, look at SOP_CPlusPlusBase.h 35 | 36 | class FilterDAT : public DAT_CPlusPlusBase 37 | { 38 | public: 39 | FilterDAT(const OP_NodeInfo*); 40 | virtual ~FilterDAT(); 41 | 42 | virtual void getGeneralInfo(DAT_GeneralInfo*, const OP_Inputs*, void* reserved) override; 43 | 44 | virtual void execute(DAT_Output*, const OP_Inputs*, void* reserved) override; 45 | 46 | virtual void setupParameters(OP_ParameterManager*, void* reserved) override; 47 | 48 | 49 | private: 50 | void fillTable(const OP_Inputs*, DAT_Output*, const OP_DATInput*); 51 | Parameters myParms; 52 | }; 53 | 54 | #endif 55 | -------------------------------------------------------------------------------- /DAT/FilterDAT/FilterDAT.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio Version 16 4 | VisualStudioVersion = 16.0.30717.126 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "FilterDAT", "FilterDAT.vcxproj", "{3F5BEECD-FA36-459F-91B8-BB481A67EF44}" 7 | EndProject 8 | Global 9 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 10 | Debug|x64 = Debug|x64 11 | Release|x64 = Release|x64 12 | EndGlobalSection 13 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 14 | {3F5BEECD-FA36-459F-91B8-BB481A67EF44}.Debug|x64.ActiveCfg = Debug|x64 15 | {3F5BEECD-FA36-459F-91B8-BB481A67EF44}.Debug|x64.Build.0 = Debug|x64 16 | {3F5BEECD-FA36-459F-91B8-BB481A67EF44}.Release|x64.ActiveCfg = Release|x64 17 | {3F5BEECD-FA36-459F-91B8-BB481A67EF44}.Release|x64.Build.0 = Release|x64 18 | EndGlobalSection 19 | GlobalSection(SolutionProperties) = preSolution 20 | HideSolutionNode = FALSE 21 | EndGlobalSection 22 | GlobalSection(ExtensibilityGlobals) = postSolution 23 | SolutionGuid = {120FB025-F1C9-4C2D-B652-894C921DF752} 24 | EndGlobalSection 25 | EndGlobal 26 | -------------------------------------------------------------------------------- /DAT/FilterDAT/Parameters.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include "CPlusPlus_Common.h" 4 | #include "Parameters.h" 5 | 6 | #pragma region Evals 7 | 8 | CaseMenuItems 9 | Parameters::evalCase(const TD::OP_Inputs* inputs) 10 | { 11 | return static_cast(inputs->getParInt(CaseName)); 12 | } 13 | 14 | bool 15 | Parameters::evalKeepspaces(const TD::OP_Inputs* inputs) 16 | { 17 | return inputs->getParInt(KeepspacesName) ? true : false; 18 | } 19 | 20 | 21 | #pragma endregion 22 | 23 | #pragma region Setup 24 | 25 | void 26 | Parameters::setup(TD::OP_ParameterManager* manager) 27 | { 28 | { 29 | TD::OP_StringParameter p; 30 | p.name = CaseName; 31 | p.label = CaseLabel; 32 | p.page = "Filter"; 33 | p.defaultValue = "Uppercamelcase"; 34 | std::array Names = 35 | { 36 | "Uppercamelcase", 37 | "Lowercase", 38 | "Uppercase" 39 | }; 40 | std::array Labels = 41 | { 42 | "Upper Camel Case", 43 | "Lower Case", 44 | "Upper Case" 45 | }; 46 | TD::OP_ParAppendResult res = manager->appendMenu(p, Names.size(), Names.data(), Labels.data()); 47 | 48 | assert(res == TD::OP_ParAppendResult::Success); 49 | } 50 | 51 | { 52 | TD::OP_NumericParameter p; 53 | p.name = KeepspacesName; 54 | p.label = KeepspacesLabel; 55 | p.page = "Filter"; 56 | p.defaultValues[0] = false; 57 | 58 | TD::OP_ParAppendResult res = manager->appendToggle(p); 59 | 60 | assert(res == TD::OP_ParAppendResult::Success); 61 | } 62 | 63 | 64 | } 65 | 66 | #pragma endregion -------------------------------------------------------------------------------- /DAT/FilterDAT/Parameters.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | class TD::OP_Inputs; 6 | class TD::OP_ParameterManager; 7 | 8 | #pragma region ParNames and ParLabels 9 | 10 | // Names of the parameters 11 | 12 | constexpr static char CaseName[] = "Case"; 13 | constexpr static char CaseLabel[] = "Case"; 14 | 15 | constexpr static char KeepspacesName[] = "Keepspaces"; 16 | constexpr static char KeepspacesLabel[] = "Keep Spaces"; 17 | 18 | 19 | #pragma endregion 20 | 21 | #pragma region Menus 22 | enum class CaseMenuItems 23 | { 24 | Uppercamelcase, 25 | Lowercase, 26 | Uppercase 27 | }; 28 | 29 | #pragma endregion 30 | 31 | 32 | #pragma region Parameters 33 | class Parameters 34 | { 35 | public: 36 | static void setup(TD::OP_ParameterManager*); 37 | 38 | // Case 39 | static CaseMenuItems evalCase(const TD::OP_Inputs* inputs); 40 | 41 | // Keep Spaces 42 | static bool evalKeepspaces(const TD::OP_Inputs* inputs); 43 | 44 | 45 | }; 46 | #pragma endregion -------------------------------------------------------------------------------- /DAT/FilterDAT/README.md: -------------------------------------------------------------------------------- 1 | # Filter DAT 2 | 3 | This is a simple examlpe of a Custom Filter DAT operator. 4 | Its functionality is to convert input strings into `Upper Camel Case`, `Upper Case` or `Lower Case` as well as the possibility to strip spaces from the input string. 5 | 6 | ## Parameters 7 | * **Case** - select how to convert the input string 8 | * _Upper Camel Case_ - will convert the string to Upper Camel Case. For example `ARUCO Markers` will become `Aruco Markers` 9 | * _Lower Case_ - will convert the string to Lower Case. For example `ARUCO Markers` will become `aruco markers` 10 | * _Upper Case_ - will convert the string to Upper Case. For example `ARUCO Markers` will become `ARUCO MARKERS` 11 | * **Keep Spaces** - When enabled will preserve spaces in the input string, otherwise will strip spaces. 12 | -------------------------------------------------------------------------------- /DAT/GeneratorDAT/GeneratorDAT.cpp: -------------------------------------------------------------------------------- 1 | /* Shared Use License: This file is owned by Derivative Inc. (Derivative) 2 | * and can only be used, and/or modified for use, in conjunction with 3 | * Derivative's TouchDesigner software, and only if you are a licensee who has 4 | * accepted Derivative's TouchDesigner license or assignment agreement 5 | * (which also govern the use of this file). You may share or redistribute 6 | * a modified version of this file provided the following conditions are met: 7 | * 8 | * 1. The shared file or redistribution must retain the information set out 9 | * above and this list of conditions. 10 | * 2. Derivative's name (Derivative Inc.) or its trademarks may not be used 11 | * to endorse or promote products derived from this file without specific 12 | * prior written permission from Derivative. 13 | */ 14 | 15 | #include "GeneratorDAT.h" 16 | #include "Parameters.h" 17 | 18 | #include 19 | #include 20 | #include 21 | 22 | static const char ALPHANUM[] = 23 | "0123456789" 24 | "ABCDEFGHIJKLMNOPQRSTUVWXYZ" 25 | "abcdefghijklmnopqrstuvwxyz"; 26 | 27 | // These functions are basic C function, which the DLL loader can find 28 | // much easier than finding a C++ Class. 29 | // The DLLEXPORT prefix is needed so the compile exports these functions from the .dll 30 | // you are creating 31 | extern "C" 32 | { 33 | 34 | DLLEXPORT 35 | void 36 | FillDATPluginInfo(DAT_PluginInfo *info) 37 | { 38 | // For more information on CHOP_PluginInfo see CHOP_CPlusPlusBase.h 39 | 40 | // Always set this to CHOPCPlusPlusAPIVersion. 41 | info->apiVersion = DATCPlusPlusAPIVersion; 42 | 43 | // For more information on OP_CustomOPInfo see CPlusPlus_Common.h 44 | OP_CustomOPInfo& customInfo = info->customOPInfo; 45 | 46 | // Unique name of the node which starts with an upper case letter, followed by lower case letters or numbers 47 | customInfo.opType->setString("Generator"); 48 | // English readable name 49 | customInfo.opLabel->setString("Generator"); 50 | // Information of the author of the node 51 | customInfo.authorName->setString("Author Name"); 52 | customInfo.authorEmail->setString("email@email"); 53 | 54 | // This Dat takes no input 55 | customInfo.minInputs = 0; 56 | customInfo.maxInputs = 0; 57 | } 58 | 59 | DLLEXPORT 60 | DAT_CPlusPlusBase* 61 | CreateDATInstance(const OP_NodeInfo* info) 62 | { 63 | // Return a new instance of your class every time this is called. 64 | // It will be called once per DAT that is using the .dll 65 | return new GeneratorDAT(info); 66 | } 67 | 68 | DLLEXPORT 69 | void 70 | DestroyDATInstance(DAT_CPlusPlusBase* instance) 71 | { 72 | // Delete the instance here, this will be called when 73 | // Touch is shutting down, when the DAT using that instance is deleted, or 74 | // if the DAT loads a different DLL 75 | delete (GeneratorDAT*)instance; 76 | } 77 | 78 | }; 79 | 80 | GeneratorDAT::GeneratorDAT(const OP_NodeInfo* info) : 81 | myRNG{} 82 | { 83 | } 84 | 85 | GeneratorDAT::~GeneratorDAT() 86 | { 87 | } 88 | 89 | void 90 | GeneratorDAT::getGeneralInfo(DAT_GeneralInfo* ginfo, const OP_Inputs*, void*) 91 | { 92 | // This will cause the node to not cook every frame 93 | ginfo->cookEveryFrameIfAsked = false; 94 | } 95 | 96 | void 97 | GeneratorDAT::execute(DAT_Output* output, const OP_Inputs* inputs, void*) 98 | { 99 | double mySeed = myParms.evalSeed(inputs); 100 | unsigned int* tmp = reinterpret_cast(&mySeed); 101 | myRNG.seed(*tmp); 102 | 103 | output->setOutputDataType(DAT_OutDataType::Table); 104 | output->setTableSize(myParms.evalRows(inputs), myParms.evalColumns(inputs)); 105 | 106 | fillTable(inputs, output); 107 | } 108 | 109 | void 110 | GeneratorDAT::setupParameters(OP_ParameterManager* manager, void*) 111 | { 112 | myParms.setup(manager); 113 | } 114 | 115 | void 116 | GeneratorDAT::fillTable(const OP_Inputs* inputs, DAT_Output* out) 117 | { 118 | 119 | for (int i = 0; i < myParms.evalRows(inputs); ++i) 120 | { 121 | for (int j = 0; j < myParms.evalColumns(inputs); ++j) 122 | { 123 | out->setCellString(i, j, generateString(inputs).c_str()); 124 | } 125 | } 126 | } 127 | 128 | std::string 129 | GeneratorDAT::generateString(const OP_Inputs* inputs) 130 | { 131 | std::uniform_int_distribution<> dis(0, sizeof(ALPHANUM) - 2); 132 | std::string ret{}; 133 | for (int i = 0; i 22 | 23 | using namespace TD; 24 | 25 | /* 26 | This example implements a DAT that generates random text. This DAT is a generator so it takes 27 | no inputs. 28 | 29 | It takes the following parameters: 30 | - Seed: A number used to initialize the pseudorandom generator. 31 | - Rows: The number of rows to output. 32 | - Columns: The number of columns to output. 33 | - Length: The length of the text in each cell of the table. 34 | */ 35 | 36 | // Check methods [getNumInfoCHOPChans, getInfoCHOPChan, getInfoDATSize, getInfoDATEntries] 37 | // if you want to output values to the Info CHOP/DAT 38 | 39 | // To get more help about these functions, look at SOP_CPlusPlusBase.h 40 | 41 | class GeneratorDAT : public DAT_CPlusPlusBase 42 | { 43 | public: 44 | GeneratorDAT(const OP_NodeInfo*); 45 | virtual ~GeneratorDAT(); 46 | 47 | virtual void getGeneralInfo(DAT_GeneralInfo*, const OP_Inputs*, void* reserved) override; 48 | 49 | virtual void execute(DAT_Output*, const OP_Inputs*, void*) override; 50 | 51 | virtual void setupParameters(OP_ParameterManager*, void*) override; 52 | 53 | private: 54 | 55 | void fillTable(const OP_Inputs*, DAT_Output*); 56 | 57 | std::string generateString(const OP_Inputs*); 58 | 59 | std::mt19937 myRNG; 60 | 61 | Parameters myParms; 62 | }; 63 | 64 | #endif 65 | -------------------------------------------------------------------------------- /DAT/GeneratorDAT/GeneratorDAT.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio Version 16 4 | VisualStudioVersion = 16.0.30717.126 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "GeneratorDAT", "DATGenerator.vcxproj", "{3F5BEECD-FA36-459F-91B8-BB481A67EF44}" 7 | EndProject 8 | Global 9 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 10 | Debug|x64 = Debug|x64 11 | Release|x64 = Release|x64 12 | EndGlobalSection 13 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 14 | {3F5BEECD-FA36-459F-91B8-BB481A67EF44}.Debug|x64.ActiveCfg = Debug|x64 15 | {3F5BEECD-FA36-459F-91B8-BB481A67EF44}.Debug|x64.Build.0 = Debug|x64 16 | {3F5BEECD-FA36-459F-91B8-BB481A67EF44}.Release|x64.ActiveCfg = Release|x64 17 | {3F5BEECD-FA36-459F-91B8-BB481A67EF44}.Release|x64.Build.0 = Release|x64 18 | EndGlobalSection 19 | GlobalSection(SolutionProperties) = preSolution 20 | HideSolutionNode = FALSE 21 | EndGlobalSection 22 | GlobalSection(ExtensibilityGlobals) = postSolution 23 | SolutionGuid = {2C6B833C-F4EE-4C0E-A0BA-F39ACF814BEB} 24 | EndGlobalSection 25 | EndGlobal 26 | -------------------------------------------------------------------------------- /DAT/GeneratorDAT/Parameters.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include "CPlusPlus_Common.h" 4 | #include "Parameters.h" 5 | 6 | #pragma region Evals 7 | 8 | double 9 | Parameters::evalSeed(const TD::OP_Inputs* inputs) 10 | { 11 | return inputs->getParDouble(SeedName); 12 | } 13 | 14 | int 15 | Parameters::evalRows(const TD::OP_Inputs* inputs) 16 | { 17 | return inputs->getParInt(RowsName); 18 | } 19 | 20 | int 21 | Parameters::evalColumns(const TD::OP_Inputs* inputs) 22 | { 23 | return inputs->getParInt(ColumnsName); 24 | } 25 | 26 | int 27 | Parameters::evalLength(const TD::OP_Inputs* inputs) 28 | { 29 | return inputs->getParInt(LengthName); 30 | } 31 | 32 | 33 | #pragma endregion 34 | 35 | #pragma region Setup 36 | 37 | void 38 | Parameters::setup(TD::OP_ParameterManager* manager) 39 | { 40 | { 41 | TD::OP_NumericParameter p; 42 | p.name = SeedName; 43 | p.label = SeedLabel; 44 | p.page = "Generator"; 45 | p.defaultValues[0] = 1.0; 46 | p.minSliders[0] = 0.0; 47 | p.maxSliders[0] = 10.0; 48 | p.minValues[0] = 0.0; 49 | p.maxValues[0] = 1.0; 50 | p.clampMins[0] = false; 51 | p.clampMaxes[0] = false; 52 | TD::OP_ParAppendResult res = manager->appendFloat(p); 53 | 54 | assert(res == TD::OP_ParAppendResult::Success); 55 | } 56 | 57 | { 58 | TD::OP_NumericParameter p; 59 | p.name = RowsName; 60 | p.label = RowsLabel; 61 | p.page = "Generator"; 62 | p.defaultValues[0] = 3; 63 | p.minSliders[0] = 0.0; 64 | p.maxSliders[0] = 100.0; 65 | p.minValues[0] = 0.0; 66 | p.maxValues[0] = 1.0; 67 | p.clampMins[0] = true; 68 | p.clampMaxes[0] = false; 69 | TD::OP_ParAppendResult res = manager->appendInt(p); 70 | 71 | assert(res == TD::OP_ParAppendResult::Success); 72 | } 73 | 74 | { 75 | TD::OP_NumericParameter p; 76 | p.name = ColumnsName; 77 | p.label = ColumnsLabel; 78 | p.page = "Generator"; 79 | p.defaultValues[0] = 4; 80 | p.minSliders[0] = 0.0; 81 | p.maxSliders[0] = 100.0; 82 | p.minValues[0] = 0.0; 83 | p.maxValues[0] = 1.0; 84 | p.clampMins[0] = true; 85 | p.clampMaxes[0] = false; 86 | TD::OP_ParAppendResult res = manager->appendInt(p); 87 | 88 | assert(res == TD::OP_ParAppendResult::Success); 89 | } 90 | 91 | { 92 | TD::OP_NumericParameter p; 93 | p.name = LengthName; 94 | p.label = LengthLabel; 95 | p.page = "Generator"; 96 | p.defaultValues[0] = 5; 97 | p.minSliders[0] = 0.0; 98 | p.maxSliders[0] = 100.0; 99 | p.minValues[0] = 0.0; 100 | p.maxValues[0] = 1.0; 101 | p.clampMins[0] = true; 102 | p.clampMaxes[0] = false; 103 | TD::OP_ParAppendResult res = manager->appendInt(p); 104 | 105 | assert(res == TD::OP_ParAppendResult::Success); 106 | } 107 | 108 | 109 | } 110 | 111 | #pragma endregion -------------------------------------------------------------------------------- /DAT/GeneratorDAT/Parameters.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | class TD::OP_Inputs; 6 | class TD::OP_ParameterManager; 7 | 8 | #pragma region ParNames and ParLabels 9 | 10 | // Names of the parameters 11 | 12 | constexpr static char SeedName[] = "Seed"; 13 | constexpr static char SeedLabel[] = "Seed"; 14 | 15 | constexpr static char RowsName[] = "Rows"; 16 | constexpr static char RowsLabel[] = "Rows"; 17 | 18 | constexpr static char ColumnsName[] = "Columns"; 19 | constexpr static char ColumnsLabel[] = "Columns"; 20 | 21 | constexpr static char LengthName[] = "Length"; 22 | constexpr static char LengthLabel[] = "Length"; 23 | 24 | 25 | #pragma endregion 26 | 27 | #pragma region Menus 28 | #pragma endregion 29 | 30 | 31 | #pragma region Parameters 32 | class Parameters 33 | { 34 | public: 35 | static void setup(TD::OP_ParameterManager*); 36 | 37 | // Seed 38 | static double evalSeed(const TD::OP_Inputs* inputs); 39 | 40 | // Rows 41 | static int evalRows(const TD::OP_Inputs* inputs); 42 | 43 | // Columns 44 | static int evalColumns(const TD::OP_Inputs* inputs); 45 | 46 | // Length 47 | static int evalLength(const TD::OP_Inputs* inputs); 48 | 49 | 50 | }; 51 | #pragma endregion -------------------------------------------------------------------------------- /DAT/GeneratorDAT/README.md: -------------------------------------------------------------------------------- 1 | # Generator DAT 2 | 3 | This is a simple examlpe of a Custom Generator DAT operator. 4 | Its functionality is to create random strings. 5 | 6 | ## Parameters 7 | * **Seed** - Change the seed for the random generator. 8 | * **Rows** - Specify number of rows for the created table. 9 | * **Columns** - Specify number of columns for the created table. 10 | * **Length** - Specify length of random string generated in each cell. 11 | -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | Shared Use License: This file is owned by Derivative Inc. (Derivative) 2 | and can only be used, and/or modified for use, in conjunction with 3 | Derivative's TouchDesigner software, and only if you are a licensee who has 4 | accepted Derivative's TouchDesigner license or assignment agreement 5 | (which also govern the use of this file). You may share or redistribute 6 | a modified version of this file provided the following conditions are met: 7 | 8 | 1. The shared file or redistribution must retain the information set out 9 | above and this list of conditions. 10 | 2. Derivative's name (Derivative Inc.) or its trademarks may not be used 11 | to endorse or promote products derived from this file without specific 12 | prior written permission from Derivative. 13 | -------------------------------------------------------------------------------- /SOP/FilterSOP/FilterSOP.h: -------------------------------------------------------------------------------- 1 | /* Shared Use License: This file is owned by Derivative Inc. (Derivative) 2 | * and can only be used, and/or modified for use, in conjunction with 3 | * Derivative's TouchDesigner software, and only if you are a licensee who has 4 | * accepted Derivative's TouchDesigner license or assignment agreement 5 | * (which also govern the use of this file). You may share or redistribute 6 | * a modified version of this file provided the following conditions are met: 7 | * 8 | * 1. The shared file or redistribution must retain the information set out 9 | * above and this list of conditions. 10 | * 2. Derivative's name (Derivative Inc.) or its trademarks may not be used 11 | * to endorse or promote products derived from this file without specific 12 | * prior written permission from Derivative. 13 | */ 14 | 15 | #ifndef __FilterSOP__ 16 | #define __FilterSOP__ 17 | 18 | #include "SOP_CPlusPlusBase.h" 19 | #include "Parameters.h" 20 | #include 21 | 22 | 23 | /* 24 | This example implements a SOP which takes the following parameters: 25 | - Translate CHOP: A CHOP with 3 channels whose value determines a translation for the input SOP. 26 | 27 | This SOP is a filter and it takes one input SOP with triangulated geometry. 28 | */ 29 | 30 | // Check methods [getNumInfoCHOPChans, getInfoCHOPChan, getInfoDATSize, getInfoDATEntries] 31 | // if you want to output values to the Info CHOP/DAT 32 | 33 | // To get more help about these functions, look at SOP_CPlusPlusBase.h 34 | class FilterSOP : public TD::SOP_CPlusPlusBase 35 | { 36 | public: 37 | FilterSOP(const TD::OP_NodeInfo* info); 38 | virtual ~FilterSOP(); 39 | 40 | virtual void getGeneralInfo(TD::SOP_GeneralInfo*, const TD::OP_Inputs*, void*) override; 41 | 42 | virtual void execute(TD::SOP_Output*, const TD::OP_Inputs*, void*) override; 43 | 44 | virtual void executeVBO(TD::SOP_VBOOutput*, const TD::OP_Inputs*, void*) override; 45 | 46 | virtual void setupParameters(TD::OP_ParameterManager* manager, void*) override; 47 | 48 | virtual void getWarningString(TD::OP_String*, void*) override; 49 | 50 | 51 | private: 52 | void copyPointsTranslated(TD::SOP_Output*, const TD::OP_SOPInput*, const TD::Vector&) const; 53 | 54 | // Before calling this functions SOP_Output should contain as many points as OP_SOPInput 55 | void copyAttributes(TD::SOP_Output*, const TD::OP_SOPInput*) const; 56 | 57 | void copyNormals(TD::SOP_Output*, const TD::OP_SOPInput*) const; 58 | 59 | void copyColors(TD::SOP_Output*, const TD::OP_SOPInput*) const; 60 | 61 | void copyTextures(TD::SOP_Output*, const TD::OP_SOPInput*) const; 62 | 63 | void copyCustomAttributes(TD::SOP_Output*, const TD::OP_SOPInput*) const; 64 | // This method returns true if the input geometry only has triangles and lines 65 | void copyPrimitives(TD::SOP_Output*, const TD::OP_SOPInput*); 66 | 67 | TD::Vector getTranslate(const TD::OP_CHOPInput*); 68 | 69 | std::string myWarningString; 70 | 71 | Parameters myParms; 72 | }; 73 | 74 | #endif // !__FilterSOP__ 75 | -------------------------------------------------------------------------------- /SOP/FilterSOP/FilterSOP.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio Version 16 4 | VisualStudioVersion = 16.0.30011.22 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "FilterSOP", "FilterSOP.vcxproj", "{3F5BEECD-FA36-459F-91B8-BB481A67EF44}" 7 | EndProject 8 | Global 9 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 10 | Debug|x64 = Debug|x64 11 | Release|x64 = Release|x64 12 | EndGlobalSection 13 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 14 | {3F5BEECD-FA36-459F-91B8-BB481A67EF44}.Debug|x64.ActiveCfg = Debug|x64 15 | {3F5BEECD-FA36-459F-91B8-BB481A67EF44}.Debug|x64.Build.0 = Debug|x64 16 | {3F5BEECD-FA36-459F-91B8-BB481A67EF44}.Release|x64.ActiveCfg = Release|x64 17 | {3F5BEECD-FA36-459F-91B8-BB481A67EF44}.Release|x64.Build.0 = Release|x64 18 | EndGlobalSection 19 | GlobalSection(SolutionProperties) = preSolution 20 | HideSolutionNode = FALSE 21 | EndGlobalSection 22 | GlobalSection(ExtensibilityGlobals) = postSolution 23 | SolutionGuid = {CDCA304D-7173-47CC-BC43-257E4444266C} 24 | EndGlobalSection 25 | EndGlobal 26 | -------------------------------------------------------------------------------- /SOP/FilterSOP/FilterSOP.vcxproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | Debug 6 | x64 7 | 8 | 9 | Release 10 | x64 11 | 12 | 13 | 14 | {3F5BEECD-FA36-459F-91B8-BB481A67EF44} 15 | FilterSOP 16 | Win32Proj 17 | 10.0 18 | FilterSOP 19 | 20 | 21 | 22 | DynamicLibrary 23 | Unicode 24 | true 25 | v142 26 | 27 | 28 | DynamicLibrary 29 | Unicode 30 | v142 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | <_ProjectFileVersion>10.0.40219.1 44 | $(SolutionDir)$(Configuration)\ 45 | $(Configuration)\ 46 | false 47 | $(SolutionDir)$(Configuration)\ 48 | $(Configuration)\ 49 | false 50 | 51 | 52 | 53 | Disabled 54 | WIN32;_DEBUG;_WINDOWS;_USRDLL;%(PreprocessorDefinitions) 55 | EnableFastChecks 56 | MultiThreadedDebugDLL 57 | 58 | 59 | Level3 60 | ProgramDatabase 61 | stdcpp17 62 | true 63 | 64 | 65 | true 66 | Windows 67 | 68 | 69 | 70 | 71 | MultiThreadedDLL 72 | 73 | 74 | Level3 75 | ProgramDatabase 76 | 77 | 78 | true 79 | Windows 80 | true 81 | true 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | -------------------------------------------------------------------------------- /SOP/FilterSOP/GL_Extensions.h: -------------------------------------------------------------------------------- 1 | // Stub file for simpler CHOP usage than an OpenGLTOP 2 | 3 | #include 4 | -------------------------------------------------------------------------------- /SOP/FilterSOP/Parameters.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include "CPlusPlus_Common.h" 4 | #include "Parameters.h" 5 | 6 | #pragma region Evals 7 | 8 | const TD::OP_CHOPInput* 9 | Parameters::evalTranslatechop(const TD::OP_Inputs* inputs) 10 | { 11 | return inputs->getParCHOP(TranslatechopName); 12 | } 13 | 14 | 15 | #pragma endregion 16 | 17 | #pragma region Setup 18 | 19 | void 20 | Parameters::setup(TD::OP_ParameterManager* manager) 21 | { 22 | { 23 | TD::OP_StringParameter p; 24 | p.name = TranslatechopName; 25 | p.label = TranslatechopLabel; 26 | p.page = "Filter"; 27 | p.defaultValue = ""; 28 | TD::OP_ParAppendResult res = manager->appendCHOP(p); 29 | 30 | assert(res == TD::OP_ParAppendResult::Success); 31 | } 32 | 33 | 34 | } 35 | 36 | #pragma endregion -------------------------------------------------------------------------------- /SOP/FilterSOP/Parameters.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | class TD::OP_Inputs; 6 | class TD::OP_ParameterManager; 7 | 8 | #pragma region ParNames and ParLabels 9 | 10 | // Names of the parameters 11 | 12 | constexpr static char TranslatechopName[] = "Translatechop"; 13 | constexpr static char TranslatechopLabel[] = "Translate CHOP"; 14 | 15 | 16 | #pragma endregion 17 | 18 | #pragma region Menus 19 | #pragma endregion 20 | 21 | 22 | #pragma region Parameters 23 | class Parameters 24 | { 25 | public: 26 | static void setup(TD::OP_ParameterManager*); 27 | 28 | // Translate CHOP 29 | static const TD::OP_CHOPInput* evalTranslatechop(const TD::OP_Inputs* inputs); 30 | 31 | 32 | }; 33 | #pragma endregion -------------------------------------------------------------------------------- /SOP/FilterSOP/README.md: -------------------------------------------------------------------------------- 1 | # Filter SOP 2 | This basic SOP example uses a 3 channels CHOP to transform the position of the incoming SOP. 3 | 4 | ## Parameters 5 | * **Translate CHOP** - CHOP with 3 channels, one for each translate axis. 6 | -------------------------------------------------------------------------------- /SOP/GeneratorSOP/GL_Extensions.h: -------------------------------------------------------------------------------- 1 | // Stub file for simpler CHOP usage than an OpenGLTOP 2 | 3 | #include 4 | -------------------------------------------------------------------------------- /SOP/GeneratorSOP/GeneratorSOP.h: -------------------------------------------------------------------------------- 1 | /* Shared Use License: This file is owned by Derivative Inc. (Derivative) 2 | * and can only be used, and/or modified for use, in conjunction with 3 | * Derivative's TouchDesigner software, and only if you are a licensee who has 4 | * accepted Derivative's TouchDesigner license or assignment agreement 5 | * (which also govern the use of this file). You may share or redistribute 6 | * a modified version of this file provided the following conditions are met: 7 | * 8 | * 1. The shared file or redistribution must retain the information set out 9 | * above and this list of conditions. 10 | * 2. Derivative's name (Derivative Inc.) or its trademarks may not be used 11 | * to endorse or promote products derived from this file without specific 12 | * prior written permission from Derivative. 13 | */ 14 | 15 | #ifndef __GeneratorSOP__ 16 | #define __GeneratorSOP__ 17 | 18 | #include "SOP_CPlusPlusBase.h" 19 | #include "ShapeGenerator.h" 20 | #include "Parameters.h" 21 | 22 | /* 23 | This example implements a SOP which takes the following parameters: 24 | - Shape: One of [Point, Line, Square, Cube] which is the shape this SOP outputs. 25 | - Color: The color applied to the shape. 26 | - GPU Direct: Whether the shape is loaded to the GPU. 27 | 28 | This SOP is a generator and it takes no input. 29 | */ 30 | 31 | // Check methods [getNumInfoCHOPChans, getInfoCHOPChan, getInfoDATSize, getInfoDATEntries] 32 | // if you want to output values to the Info CHOP/DAT 33 | 34 | // To get more help about these functions, look at SOP_CPlusPlusBase.h 35 | class GeneratorSOP : public TD::SOP_CPlusPlusBase 36 | { 37 | public: 38 | GeneratorSOP(const TD::OP_NodeInfo* info); 39 | virtual ~GeneratorSOP(); 40 | 41 | virtual void getGeneralInfo(TD::SOP_GeneralInfo*, const TD::OP_Inputs*, void*) override; 42 | 43 | virtual void execute(TD::SOP_Output*, const TD::OP_Inputs*, void*) override; 44 | 45 | virtual void executeVBO(TD::SOP_VBOOutput*, const TD::OP_Inputs*, void*) override; 46 | 47 | virtual void setupParameters(TD::OP_ParameterManager*, void*) override; 48 | 49 | private: 50 | // Class to construct geometry 51 | ShapeGenerator myShapeGenerator; 52 | 53 | Parameters myParms; 54 | }; 55 | 56 | #endif // !__GeneratorSOP__ 57 | -------------------------------------------------------------------------------- /SOP/GeneratorSOP/GeneratorSOP.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio Version 16 4 | VisualStudioVersion = 16.0.30011.22 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "GeneratorSOP", "GeneratorSOP.vcxproj", "{3F5BEECD-FA36-459F-91B8-BB481A67EF44}" 7 | EndProject 8 | Global 9 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 10 | Debug|x64 = Debug|x64 11 | Release|x64 = Release|x64 12 | EndGlobalSection 13 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 14 | {3F5BEECD-FA36-459F-91B8-BB481A67EF44}.Debug|x64.ActiveCfg = Debug|x64 15 | {3F5BEECD-FA36-459F-91B8-BB481A67EF44}.Debug|x64.Build.0 = Debug|x64 16 | {3F5BEECD-FA36-459F-91B8-BB481A67EF44}.Release|x64.ActiveCfg = Release|x64 17 | {3F5BEECD-FA36-459F-91B8-BB481A67EF44}.Release|x64.Build.0 = Release|x64 18 | EndGlobalSection 19 | GlobalSection(SolutionProperties) = preSolution 20 | HideSolutionNode = FALSE 21 | EndGlobalSection 22 | GlobalSection(ExtensibilityGlobals) = postSolution 23 | SolutionGuid = {CDCA304D-7173-47CC-BC43-257E4444266C} 24 | EndGlobalSection 25 | EndGlobal 26 | -------------------------------------------------------------------------------- /SOP/GeneratorSOP/Parameters.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include "CPlusPlus_Common.h" 4 | #include "Parameters.h" 5 | 6 | #pragma region Evals 7 | 8 | ShapeMenuItems 9 | Parameters::evalShape(const TD::OP_Inputs* inputs) 10 | { 11 | return static_cast(inputs->getParInt(ShapeName)); 12 | } 13 | 14 | TD::Color 15 | Parameters::evalColor(const TD::OP_Inputs* inputs) 16 | { 17 | std::array vals; 18 | inputs->getParDouble4(ColorName, vals[0], vals[1], vals[2], vals[3]); 19 | return TD::Color((float)vals[0], (float)vals[1], (float)vals[2], (float)vals[3]); 20 | } 21 | 22 | bool 23 | Parameters::evalGpudirect(const TD::OP_Inputs* inputs) 24 | { 25 | return inputs->getParInt(GpudirectName) ? true : false; 26 | } 27 | 28 | 29 | #pragma endregion 30 | 31 | #pragma region Setup 32 | 33 | void 34 | Parameters::setup(TD::OP_ParameterManager* manager) 35 | { 36 | { 37 | TD::OP_StringParameter p; 38 | p.name = ShapeName; 39 | p.label = ShapeLabel; 40 | p.page = "Generator"; 41 | p.defaultValue = "Cube"; 42 | std::array Names = 43 | { 44 | "Point", 45 | "Line", 46 | "Square", 47 | "Cube" 48 | }; 49 | std::array Labels = 50 | { 51 | "Point", 52 | "Line", 53 | "Square", 54 | "Cube" 55 | }; 56 | TD::OP_ParAppendResult res = manager->appendMenu(p, Names.size(), Names.data(), Labels.data()); 57 | 58 | assert(res == TD::OP_ParAppendResult::Success); 59 | } 60 | 61 | { 62 | TD::OP_NumericParameter p; 63 | p.name = ColorName; 64 | p.label = ColorLabel; 65 | p.page = "Generator"; 66 | 67 | const int ArraySize = 4; 68 | 69 | const std::array DefaultValues = { 1.0, 1.0, 1.0, 1.0 }; 70 | const std::array MinSliders = { 0.0, 0.0, 0.0, 0.0 }; 71 | const std::array MaxSliders = { 1.0, 1.0, 1.0, 1.0 }; 72 | const std::array MinValues = { 0.0, 0.0, 0.0, 0.0 }; 73 | const std::array MaxValues = { 1.0, 1.0, 1.0, 1.0 }; 74 | const std::array ClampMins = { false, false, false, false }; 75 | const std::array ClampMaxes = { false, false, false, false }; 76 | for (int i = 0; i < DefaultValues.size(); ++i) 77 | { 78 | p.defaultValues[i] = DefaultValues[i]; 79 | p.minSliders[i] = MinSliders[i]; 80 | p.maxSliders[i] = MaxSliders[i]; 81 | p.minValues[i] = MinValues[i]; 82 | p.maxValues[i] = MaxValues[i]; 83 | p.clampMins[i] = ClampMins[i]; 84 | p.clampMaxes[i] = ClampMaxes[i]; 85 | } 86 | TD::OP_ParAppendResult res = manager->appendRGBA(p); 87 | 88 | assert(res == TD::OP_ParAppendResult::Success); 89 | } 90 | 91 | { 92 | TD::OP_NumericParameter p; 93 | p.name = GpudirectName; 94 | p.label = GpudirectLabel; 95 | p.page = "Generator"; 96 | p.defaultValues[0] = false; 97 | 98 | TD::OP_ParAppendResult res = manager->appendToggle(p); 99 | 100 | assert(res == TD::OP_ParAppendResult::Success); 101 | } 102 | 103 | 104 | } 105 | 106 | #pragma endregion -------------------------------------------------------------------------------- /SOP/GeneratorSOP/Parameters.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | class TD::OP_Inputs; 6 | class TD::OP_ParameterManager; 7 | 8 | #pragma region ParNames and ParLabels 9 | 10 | // Names of the parameters 11 | 12 | constexpr static char ShapeName[] = "Shape"; 13 | constexpr static char ShapeLabel[] = "Shape"; 14 | 15 | constexpr static char ColorName[] = "Color"; 16 | constexpr static char ColorLabel[] = "Color"; 17 | 18 | constexpr static char GpudirectName[] = "Gpudirect"; 19 | constexpr static char GpudirectLabel[] = "GPU Direct"; 20 | 21 | 22 | #pragma endregion 23 | 24 | #pragma region Menus 25 | enum class ShapeMenuItems 26 | { 27 | Point, 28 | Line, 29 | Square, 30 | Cube 31 | }; 32 | 33 | #pragma endregion 34 | 35 | 36 | #pragma region Parameters 37 | class Parameters 38 | { 39 | public: 40 | static void setup(TD::OP_ParameterManager*); 41 | 42 | // Shape 43 | static ShapeMenuItems evalShape(const TD::OP_Inputs* inputs); 44 | 45 | // Color 46 | static TD::Color evalColor(const TD::OP_Inputs* inputs); 47 | 48 | // GPU Direct 49 | static bool evalGpudirect(const TD::OP_Inputs* inputs); 50 | 51 | 52 | }; 53 | #pragma endregion -------------------------------------------------------------------------------- /SOP/GeneratorSOP/README.md: -------------------------------------------------------------------------------- 1 | # Generator SOP 2 | This basic Generator SOP example can be used to generate SOP data such as point, lines, squares... etc. 3 | 4 | ## Parameters 5 | * **Shape** - The shape of the SOP to generate. 6 | * **Point** - A single point. 7 | * **Line** - A simple 2 points line. 8 | * **Square** - A triangulated square. 9 | * **Cube** - A triangulated cube. 10 | * **Color** - The point color attribute value. 11 | * **GPU Direct** - Load the geometry directly to the GPU. 12 | -------------------------------------------------------------------------------- /SOP/GeneratorSOP/ShapeGenerator.h: -------------------------------------------------------------------------------- 1 | /* Shared Use License: This file is owned by Derivative Inc. (Derivative) 2 | * and can only be used, and/or modified for use, in conjunction with 3 | * Derivative's TouchDesigner software, and only if you are a licensee who has 4 | * accepted Derivative's TouchDesigner license or assignment agreement 5 | * (which also govern the use of this file). You may share or redistribute 6 | * a modified version of this file provided the following conditions are met: 7 | * 8 | * 1. The shared file or redistribution must retain the information set out 9 | * above and this list of conditions. 10 | * 2. Derivative's name (Derivative Inc.) or its trademarks may not be used 11 | * to endorse or promote products derived from this file without specific 12 | * prior written permission from Derivative. 13 | */ 14 | 15 | #ifndef __ShapeGenerator__ 16 | #define __ShapeGenerator__ 17 | 18 | #include 19 | #include "CPlusPlus_Common.h" 20 | #include "SOP_CPlusPlusBase.h" 21 | 22 | 23 | class ShapeGenerator 24 | { 25 | public: 26 | void outputDot(TD::SOP_Output*) const; 27 | 28 | void outputLine(TD::SOP_Output*) const; 29 | 30 | void outputSquare(TD::SOP_Output*) const; 31 | 32 | void outputCube(TD::SOP_Output*) const; 33 | 34 | // Output the shape directly to the GPU 35 | void outputDotVBO(TD::SOP_VBOOutput*); 36 | 37 | void outputLineVBO(TD::SOP_VBOOutput*); 38 | 39 | void outputSquareVBO(TD::SOP_VBOOutput*); 40 | 41 | void outputCubeVBO(TD::SOP_VBOOutput*); 42 | 43 | // Used to know how many verties we allocated last, 44 | int getLastVBONumVertices() const; 45 | 46 | private: 47 | void setPointTexCoords(TD::SOP_Output*, const TD::TexCoord* t, int numPts) const; 48 | 49 | // Cube descriptors 32 points 3 per vertex 50 | constexpr static int theCubeNumPts = 24; 51 | constexpr static int theCubeNumPrim = 12; 52 | const static std::array theCubePos; 53 | const static std::array theCubeNormals; 54 | const static std::array theCubeVertices; 55 | const static std::array theCubeTexture; 56 | 57 | // Square descriptors 58 | constexpr static int theSquareNumPts = 4; 59 | constexpr static int theSquareNumPrim = 2; 60 | const static std::array theSquarePos; 61 | const static std::array theSquareNormals; 62 | const static std::array theSquareVertices; 63 | const static std::array theSquareTexture; 64 | 65 | // Line descriptors 66 | constexpr static int theLineNumPts = 2; 67 | const static std::array theLinePos; 68 | const static std::array theLineNormals; 69 | const static std::array theLineVertices; 70 | const static std::array theLineTexture; 71 | 72 | // Point descriptors 73 | const static TD::Position thePointPos; 74 | const static TD::Vector thePointNormal; 75 | const static TD::TexCoord thePointTexture; 76 | 77 | // LastVBO allocation 78 | int myLastVBOAllocVertices; 79 | }; 80 | 81 | #endif 82 | -------------------------------------------------------------------------------- /SOP/IntersectPointsSOP/GL_Extensions.h: -------------------------------------------------------------------------------- 1 | // Stub file for simpler CHOP usage than an OpenGLTOP 2 | 3 | #include 4 | -------------------------------------------------------------------------------- /SOP/IntersectPointsSOP/IntersectPointsSOP.h: -------------------------------------------------------------------------------- 1 | /* Shared Use License: This file is owned by Derivative Inc. (Derivative) 2 | * and can only be used, and/or modified for use, in conjunction with 3 | * Derivative's TouchDesigner software, and only if you are a licensee who has 4 | * accepted Derivative's TouchDesigner license or assignment agreement 5 | * (which also govern the use of this file). You may share or redistribute 6 | * a modified version of this file provided the following conditions are met: 7 | * 8 | * 1. The shared file or redistribution must retain the information set out 9 | * above and this list of conditions. 10 | * 2. Derivative's name (Derivative Inc.) or its trademarks may not be used 11 | * to endorse or promote products derived from this file without specific 12 | * prior written permission from Derivative. 13 | */ 14 | 15 | #ifndef __IntersectPointsSOP__ 16 | #define __IntersectPointsSOP__ 17 | 18 | #include "SOP_CPlusPlusBase.h" 19 | #include "Parameters.h" 20 | 21 | #include 22 | 23 | /* 24 | This example implements a SOP outputs the point of the first input colored 25 | whether they are inside or outside the second input. The output points have an integer attribute 26 | Inside. 1 if the point is inside, 0 otherwise. 27 | - Inside Value: Color to give to the points from the first input that are inside 28 | the geometry of the second input. 29 | - Outside Value: Color to give to the points from the first input that are outside 30 | the geometry of the second input. 31 | 32 | This SOP takes two inputs: 33 | - First: Points to be colored. 34 | - Second: Geometry to test whether points are inside or not. 35 | */ 36 | 37 | // Check methods [getNumInfoCHOPChans, getInfoCHOPChan, getInfoDATSize, getInfoDATEntries] 38 | // if you want to output values to the Info CHOP/DAT 39 | 40 | // To get more help about these functions, look at SOP_CPlusPlusBase.h 41 | class IntersectPointsSOP : public TD::SOP_CPlusPlusBase 42 | { 43 | public: 44 | IntersectPointsSOP(const TD::OP_NodeInfo* info); 45 | virtual ~IntersectPointsSOP(); 46 | 47 | virtual void getGeneralInfo(TD::SOP_GeneralInfo*, const TD::OP_Inputs*, void*) override; 48 | 49 | virtual void execute(TD::SOP_Output*, const TD::OP_Inputs*, void*) override; 50 | 51 | virtual void executeVBO(TD::SOP_VBOOutput*, const TD::OP_Inputs*, void*) override; 52 | 53 | virtual void setupParameters(TD::OP_ParameterManager*, void*) override; 54 | 55 | virtual void getWarningString(TD::OP_String*, void*) override; 56 | 57 | private: 58 | void copyPoints(TD::SOP_Output*, const TD::OP_SOPInput*) const; 59 | 60 | // Before calling this functions SOP_Output should contain as many points as OP_SOPInput 61 | void copyAttributes(TD::SOP_Output*, const TD::OP_SOPInput*) const; 62 | 63 | // This method returns true if the input geometry only has triangles and lines 64 | void copyPrimitives(TD::SOP_Output*, const TD::OP_SOPInput*); 65 | 66 | void copyNormals(TD::SOP_Output*, const TD::OP_SOPInput*) const; 67 | 68 | void copyColors(TD::SOP_Output*, const TD::OP_SOPInput*) const; 69 | 70 | void copyTextures(TD::SOP_Output*, const TD::OP_SOPInput*) const; 71 | 72 | void copyCustomAttributes(TD::SOP_Output*, const TD::OP_SOPInput*) const; 73 | 74 | std::string myWarningString; 75 | 76 | Parameters myParms; 77 | }; 78 | 79 | #endif // !__IntersectPointsSOP__ 80 | -------------------------------------------------------------------------------- /SOP/IntersectPointsSOP/IntersectPointsSOP.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio Version 16 4 | VisualStudioVersion = 16.0.30011.22 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "IntersectPointsSOP", "IntersectPointsSOP.vcxproj", "{3F5BEECD-FA36-459F-91B8-BB481A67EF44}" 7 | EndProject 8 | Global 9 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 10 | Debug|x64 = Debug|x64 11 | Release|x64 = Release|x64 12 | EndGlobalSection 13 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 14 | {3F5BEECD-FA36-459F-91B8-BB481A67EF44}.Debug|x64.ActiveCfg = Debug|x64 15 | {3F5BEECD-FA36-459F-91B8-BB481A67EF44}.Debug|x64.Build.0 = Debug|x64 16 | {3F5BEECD-FA36-459F-91B8-BB481A67EF44}.Release|x64.ActiveCfg = Release|x64 17 | {3F5BEECD-FA36-459F-91B8-BB481A67EF44}.Release|x64.Build.0 = Release|x64 18 | EndGlobalSection 19 | GlobalSection(SolutionProperties) = preSolution 20 | HideSolutionNode = FALSE 21 | EndGlobalSection 22 | GlobalSection(ExtensibilityGlobals) = postSolution 23 | SolutionGuid = {CDCA304D-7173-47CC-BC43-257E4444266C} 24 | EndGlobalSection 25 | EndGlobal 26 | -------------------------------------------------------------------------------- /SOP/IntersectPointsSOP/Parameters.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include "CPlusPlus_Common.h" 4 | #include "Parameters.h" 5 | 6 | #pragma region Evals 7 | 8 | TD::Color 9 | Parameters::evalInsidecolor(const TD::OP_Inputs* inputs) 10 | { 11 | std::array vals; 12 | inputs->getParDouble4(InsidecolorName, vals[0], vals[1], vals[2], vals[3]); 13 | return TD::Color((float)vals[0], (float)vals[1], (float)vals[2], (float)vals[3]); 14 | } 15 | 16 | TD::Color 17 | Parameters::evalOutsidecolor(const TD::OP_Inputs* inputs) 18 | { 19 | std::array vals; 20 | inputs->getParDouble4(OutsidecolorName, vals[0], vals[1], vals[2], vals[3]); 21 | return TD::Color((float)vals[0], (float)vals[1], (float)vals[2], (float)vals[3]); 22 | } 23 | 24 | 25 | #pragma endregion 26 | 27 | #pragma region Setup 28 | 29 | void 30 | Parameters::setup(TD::OP_ParameterManager* manager) 31 | { 32 | { 33 | TD::OP_NumericParameter p; 34 | p.name = InsidecolorName; 35 | p.label = InsidecolorLabel; 36 | p.page = "Intersection"; 37 | 38 | const int ArraySize = 4; 39 | 40 | const std::array DefaultValues = { 1.0, 1.0, 1.0, 1.0 }; 41 | const std::array MinSliders = { 0.0, 0.0, 0.0, 0.0 }; 42 | const std::array MaxSliders = { 1.0, 1.0, 1.0, 1.0 }; 43 | const std::array MinValues = { 0.0, 0.0, 0.0, 0.0 }; 44 | const std::array MaxValues = { 1.0, 1.0, 1.0, 1.0 }; 45 | const std::array ClampMins = { false, false, false, false }; 46 | const std::array ClampMaxes = { false, false, false, false }; 47 | for (int i = 0; i < DefaultValues.size(); ++i) 48 | { 49 | p.defaultValues[i] = DefaultValues[i]; 50 | p.minSliders[i] = MinSliders[i]; 51 | p.maxSliders[i] = MaxSliders[i]; 52 | p.minValues[i] = MinValues[i]; 53 | p.maxValues[i] = MaxValues[i]; 54 | p.clampMins[i] = ClampMins[i]; 55 | p.clampMaxes[i] = ClampMaxes[i]; 56 | } 57 | TD::OP_ParAppendResult res = manager->appendRGBA(p); 58 | 59 | assert(res == TD::OP_ParAppendResult::Success); 60 | } 61 | 62 | { 63 | TD::OP_NumericParameter p; 64 | p.name = OutsidecolorName; 65 | p.label = OutsidecolorLabel; 66 | p.page = "Intersection"; 67 | 68 | const int ArraySize = 4; 69 | 70 | const std::array DefaultValues = { 0.0, 0.0, 0.0, 1.0 }; 71 | const std::array MinSliders = { 0.0, 0.0, 0.0, 0.0 }; 72 | const std::array MaxSliders = { 1.0, 1.0, 1.0, 1.0 }; 73 | const std::array MinValues = { 0.0, 0.0, 0.0, 0.0 }; 74 | const std::array MaxValues = { 1.0, 1.0, 1.0, 1.0 }; 75 | const std::array ClampMins = { false, false, false, false }; 76 | const std::array ClampMaxes = { false, false, false, false }; 77 | for (int i = 0; i < DefaultValues.size(); ++i) 78 | { 79 | p.defaultValues[i] = DefaultValues[i]; 80 | p.minSliders[i] = MinSliders[i]; 81 | p.maxSliders[i] = MaxSliders[i]; 82 | p.minValues[i] = MinValues[i]; 83 | p.maxValues[i] = MaxValues[i]; 84 | p.clampMins[i] = ClampMins[i]; 85 | p.clampMaxes[i] = ClampMaxes[i]; 86 | } 87 | TD::OP_ParAppendResult res = manager->appendRGBA(p); 88 | 89 | assert(res == TD::OP_ParAppendResult::Success); 90 | } 91 | 92 | 93 | } 94 | 95 | #pragma endregion -------------------------------------------------------------------------------- /SOP/IntersectPointsSOP/Parameters.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | class TD::OP_Inputs; 6 | class TD::OP_ParameterManager; 7 | 8 | #pragma region ParNames and ParLabels 9 | 10 | // Names of the parameters 11 | 12 | constexpr static char InsidecolorName[] = "Insidecolor"; 13 | constexpr static char InsidecolorLabel[] = "Inside Color"; 14 | 15 | constexpr static char OutsidecolorName[] = "Outsidecolor"; 16 | constexpr static char OutsidecolorLabel[] = "Outside Color"; 17 | 18 | 19 | #pragma endregion 20 | 21 | #pragma region Menus 22 | #pragma endregion 23 | 24 | 25 | #pragma region Parameters 26 | class Parameters 27 | { 28 | public: 29 | static void setup(TD::OP_ParameterManager*); 30 | 31 | // Inside Color 32 | static TD::Color evalInsidecolor(const TD::OP_Inputs* inputs); 33 | 34 | // Outside Color 35 | static TD::Color evalOutsidecolor(const TD::OP_Inputs* inputs); 36 | 37 | 38 | }; 39 | #pragma endregion -------------------------------------------------------------------------------- /SOP/IntersectPointsSOP/README.md: -------------------------------------------------------------------------------- 1 | # Intersect Points SOP 2 | This example applies different point colors based on whether incoming SOPs are interesecting inside / outside the first incoming SOP. 3 | 4 | ## Parameters 5 | * **Inside color** - The point color attribute value applied to the SOP when another SOP is inside. 6 | * **Outside color** - The point color attribute value applied to the SOP when another SOP is outside. 7 | -------------------------------------------------------------------------------- /SOP/SpiralSOP/GL_Extensions.h: -------------------------------------------------------------------------------- 1 | // Stub file for simpler CHOP usage than an OpenGLTOP 2 | 3 | #include 4 | -------------------------------------------------------------------------------- /SOP/SpiralSOP/Parameters.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | class TD::OP_Inputs; 6 | class TD::OP_ParameterManager; 7 | 8 | #pragma region ParNames and ParLabels 9 | 10 | // Names of the parameters 11 | 12 | constexpr static char OrientationName[] = "Orientation"; 13 | constexpr static char OrientationLabel[] = "Orientation"; 14 | 15 | constexpr static char TopradiusName[] = "Topradius"; 16 | constexpr static char TopradiusLabel[] = "Top Radius"; 17 | 18 | constexpr static char BottomradiusName[] = "Bottomradius"; 19 | constexpr static char BottomradiusLabel[] = "Bottom Radius"; 20 | 21 | constexpr static char HeightName[] = "Height"; 22 | constexpr static char HeightLabel[] = "Height"; 23 | 24 | constexpr static char TurnsName[] = "Turns"; 25 | constexpr static char TurnsLabel[] = "Turns"; 26 | 27 | constexpr static char DivisionsName[] = "Divisions"; 28 | constexpr static char DivisionsLabel[] = "Divisions"; 29 | 30 | constexpr static char OutputgeometryName[] = "Outputgeometry"; 31 | constexpr static char OutputgeometryLabel[] = "Output Geometry"; 32 | 33 | constexpr static char StripwidthName[] = "Stripwidth"; 34 | constexpr static char StripwidthLabel[] = "Strip Width"; 35 | 36 | constexpr static char GpudirectName[] = "Gpudirect"; 37 | constexpr static char GpudirectLabel[] = "GPU Direct"; 38 | 39 | 40 | #pragma endregion 41 | 42 | #pragma region Menus 43 | enum class OrientationMenuItems 44 | { 45 | X, 46 | Y, 47 | Z 48 | }; 49 | 50 | enum class OutputgeometryMenuItems 51 | { 52 | Points, 53 | Line, 54 | Trianglestrip 55 | }; 56 | 57 | #pragma endregion 58 | 59 | 60 | #pragma region Parameters 61 | class Parameters 62 | { 63 | public: 64 | static void setup(TD::OP_ParameterManager*); 65 | 66 | // Orientation 67 | static OrientationMenuItems evalOrientation(const TD::OP_Inputs* inputs); 68 | 69 | // Top Radius 70 | static double evalTopradius(const TD::OP_Inputs* inputs); 71 | 72 | // Bottom Radius 73 | static double evalBottomradius(const TD::OP_Inputs* inputs); 74 | 75 | // Height 76 | static double evalHeight(const TD::OP_Inputs* inputs); 77 | 78 | // Turns 79 | static double evalTurns(const TD::OP_Inputs* inputs); 80 | 81 | // Divisions 82 | static int evalDivisions(const TD::OP_Inputs* inputs); 83 | 84 | // Output Geometry 85 | static OutputgeometryMenuItems evalOutputgeometry(const TD::OP_Inputs* inputs); 86 | 87 | // Strip Width 88 | static double evalStripwidth(const TD::OP_Inputs* inputs); 89 | 90 | // GPU Direct 91 | static bool evalGpudirect(const TD::OP_Inputs* inputs); 92 | 93 | 94 | }; 95 | #pragma endregion -------------------------------------------------------------------------------- /SOP/SpiralSOP/README.md: -------------------------------------------------------------------------------- 1 | # Spiral SOP 2 | This example demonstrate how to generate a more complex shape, in this case a spiral. 3 | 4 | ## Parameters 5 | * **Orientation** - Specify which axis the spiral is being drawn around. 6 | * **X** 7 | * **Y** 8 | * **Z** 9 | * **Top radius** - The radius at the top of the spiral. 10 | * **Bottom radius** - The radius at the bottom of the spiral. 11 | * **Height** - The length or distance between the first and last point of the spiral. 12 | * **Turns** - The number of turns the spiral should attempt to do between the top and bottom. 13 | * **Divisions** - The number of points or divisions making the spiral curve. Can vary based on the Output Geometry type. 14 | * **Output Geometry** - The geometry type making the spiral. 15 | * **Points** 16 | * **Line** 17 | * **Triangle Strip** 18 | * **Strip Width** - When triangle strip Output Geomtry type is selected, it will use the Strip Width parameter as distance between two lines. 19 | * **GPU Direct** - Load the geometry directly to the GPU. 20 | -------------------------------------------------------------------------------- /SOP/SpiralSOP/SpiralSOP.h: -------------------------------------------------------------------------------- 1 | /* Shared Use License: This file is owned by Derivative Inc. (Derivative) 2 | * and can only be used, and/or modified for use, in conjunction with 3 | * Derivative's TouchDesigner software, and only if you are a licensee who has 4 | * accepted Derivative's TouchDesigner license or assignment agreement 5 | * (which also govern the use of this file). You may share or redistribute 6 | * a modified version of this file provided the following conditions are met: 7 | * 8 | * 1. The shared file or redistribution must retain the information set out 9 | * above and this list of conditions. 10 | * 2. Derivative's name (Derivative Inc.) or its trademarks may not be used 11 | * to endorse or promote products derived from this file without specific 12 | * prior written permission from Derivative. 13 | */ 14 | 15 | #ifndef __SpiralSOP__ 16 | #define __SpiralSOP__ 17 | 18 | #include 19 | 20 | #include "SOP_CPlusPlusBase.h" 21 | #include "Parameters.h" 22 | 23 | /* 24 | This example implements a SOP outputs an Archimedean Spiral given the following 25 | parameters: 26 | - Orientation: One of [X Axis, Y Axis, Z Axis], which determines the orientation of the spiral. 27 | - Top Radius: Radius at the top of the spiral. 28 | - Bottom Radius: Radius at the bottom of the spiral. 29 | - Height: How big is the spiral about the y axis. 30 | - Turns: How many times the spiral spins. 31 | - Divisions: The number of line segments that make up the spiral. 32 | - Output Geometry: One of [Points, Line, Triangle Strip] which determines 33 | what kind of geometry we output. 34 | - Strip Width: If Output Geometry is Triangle Stirp, this determines the width 35 | of the triangle strip. 36 | - GPU Direct: If On, load geometry directly to GPU. 37 | 38 | This SOP is a generator and it takes no input. 39 | */ 40 | 41 | // Check methods [getNumInfoCHOPChans, getInfoCHOPChan, getInfoDATSize, getInfoDATEntries] 42 | // if you want to output values to the Info CHOP/DAT 43 | 44 | // To get more help about these functions, look at SOP_CPlusPlusBase.h 45 | class SpiralSOP : public TD::SOP_CPlusPlusBase 46 | { 47 | public: 48 | SpiralSOP(const TD::OP_NodeInfo* info); 49 | virtual ~SpiralSOP(); 50 | 51 | virtual void getGeneralInfo(TD::SOP_GeneralInfo*, const TD::OP_Inputs*, void*) override; 52 | 53 | virtual void execute(TD::SOP_Output*, const TD::OP_Inputs*, void*) override; 54 | 55 | virtual void executeVBO(TD::SOP_VBOOutput*, const TD::OP_Inputs*, void*) override; 56 | 57 | virtual void setupParameters(TD::OP_ParameterManager*, void*) override; 58 | 59 | private: 60 | void handleParameters(const TD::OP_Inputs*); 61 | 62 | void calculateOutputPoints(); 63 | 64 | void calculateSpiralPoints(std::vector::iterator&, int numPts); 65 | 66 | void calculateNormals(std::vector::iterator&, std::vector::const_iterator&, int numPts); 67 | 68 | void calculateTriangleStrip(); 69 | 70 | std::vector myPointPos; 71 | std::vector myNormals; 72 | std::vector myLineStrip; 73 | std::vector myLineStripTexture; 74 | TD::BoundingBox myBoundingBox; 75 | 76 | //// Parameters 77 | OrientationMenuItems myOrientation; 78 | double myTopRad; 79 | double myBotRad; 80 | double myHeight; 81 | double myTurns; 82 | int myNumPoints; 83 | OutputgeometryMenuItems myOutput; 84 | double myStripWidth; 85 | 86 | Parameters myParms; 87 | }; 88 | 89 | #endif // !__SpiralSOP__ 90 | -------------------------------------------------------------------------------- /SOP/SpiralSOP/SpiralSOP.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio Version 16 4 | VisualStudioVersion = 16.0.30011.22 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "SpiralSOP", "SpiralSOP.vcxproj", "{3F5BEECD-FA36-459F-91B8-BB481A67EF44}" 7 | EndProject 8 | Global 9 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 10 | Debug|x64 = Debug|x64 11 | Release|x64 = Release|x64 12 | EndGlobalSection 13 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 14 | {3F5BEECD-FA36-459F-91B8-BB481A67EF44}.Debug|x64.ActiveCfg = Debug|x64 15 | {3F5BEECD-FA36-459F-91B8-BB481A67EF44}.Debug|x64.Build.0 = Debug|x64 16 | {3F5BEECD-FA36-459F-91B8-BB481A67EF44}.Release|x64.ActiveCfg = Release|x64 17 | {3F5BEECD-FA36-459F-91B8-BB481A67EF44}.Release|x64.Build.0 = Release|x64 18 | EndGlobalSection 19 | GlobalSection(SolutionProperties) = preSolution 20 | HideSolutionNode = FALSE 21 | EndGlobalSection 22 | GlobalSection(ExtensibilityGlobals) = postSolution 23 | SolutionGuid = {CDCA304D-7173-47CC-BC43-257E4444266C} 24 | EndGlobalSection 25 | EndGlobal 26 | -------------------------------------------------------------------------------- /SOP/SprinkleSOP/GL_Extensions.h: -------------------------------------------------------------------------------- 1 | // Stub file for simpler CHOP usage than an OpenGLTOP 2 | 3 | #include 4 | -------------------------------------------------------------------------------- /SOP/SprinkleSOP/Parameters.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include "CPlusPlus_Common.h" 4 | #include "Parameters.h" 5 | 6 | #pragma region Evals 7 | 8 | double 9 | Parameters::evalSeed(const TD::OP_Inputs* inputs) 10 | { 11 | return inputs->getParDouble(SeedName); 12 | } 13 | 14 | GenerateMenuItems 15 | Parameters::evalGenerate(const TD::OP_Inputs* inputs) 16 | { 17 | return static_cast(inputs->getParInt(GenerateName)); 18 | } 19 | 20 | int 21 | Parameters::evalPointcount(const TD::OP_Inputs* inputs) 22 | { 23 | return inputs->getParInt(PointcountName); 24 | } 25 | 26 | bool 27 | Parameters::evalSeparatepoints(const TD::OP_Inputs* inputs) 28 | { 29 | return inputs->getParInt(SeparatepointsName) ? true : false; 30 | } 31 | 32 | double 33 | Parameters::evalMinimumdistance(const TD::OP_Inputs* inputs) 34 | { 35 | return inputs->getParDouble(MinimumdistanceName); 36 | } 37 | 38 | 39 | #pragma endregion 40 | 41 | #pragma region Setup 42 | 43 | void 44 | Parameters::setup(TD::OP_ParameterManager* manager) 45 | { 46 | { 47 | TD::OP_NumericParameter p; 48 | p.name = SeedName; 49 | p.label = SeedLabel; 50 | p.page = "Sprinkle"; 51 | p.defaultValues[0] = 1.0; 52 | p.minSliders[0] = 0.0; 53 | p.maxSliders[0] = 10.0; 54 | p.minValues[0] = 0.0; 55 | p.maxValues[0] = 1.0; 56 | p.clampMins[0] = true; 57 | p.clampMaxes[0] = false; 58 | TD::OP_ParAppendResult res = manager->appendFloat(p); 59 | 60 | assert(res == TD::OP_ParAppendResult::Success); 61 | } 62 | 63 | { 64 | TD::OP_StringParameter p; 65 | p.name = GenerateName; 66 | p.label = GenerateLabel; 67 | p.page = "Sprinkle"; 68 | p.defaultValue = "Area"; 69 | std::array Names = 70 | { 71 | "Area", 72 | "Primitive", 73 | "Boundingbox", 74 | "Volume" 75 | }; 76 | std::array Labels = 77 | { 78 | "Surface Area", 79 | "Per Primitive", 80 | "Bounding Box", 81 | "Inside Volume" 82 | }; 83 | TD::OP_ParAppendResult res = manager->appendMenu(p, Names.size(), Names.data(), Labels.data()); 84 | 85 | assert(res == TD::OP_ParAppendResult::Success); 86 | } 87 | 88 | { 89 | TD::OP_NumericParameter p; 90 | p.name = PointcountName; 91 | p.label = PointcountLabel; 92 | p.page = "Sprinkle"; 93 | p.defaultValues[0] = 100; 94 | p.minSliders[0] = 0.0; 95 | p.maxSliders[0] = 1000.0; 96 | p.minValues[0] = 0.0; 97 | p.maxValues[0] = 1.0; 98 | p.clampMins[0] = true; 99 | p.clampMaxes[0] = false; 100 | TD::OP_ParAppendResult res = manager->appendInt(p); 101 | 102 | assert(res == TD::OP_ParAppendResult::Success); 103 | } 104 | 105 | { 106 | TD::OP_NumericParameter p; 107 | p.name = SeparatepointsName; 108 | p.label = SeparatepointsLabel; 109 | p.page = "Sprinkle"; 110 | p.defaultValues[0] = false; 111 | 112 | TD::OP_ParAppendResult res = manager->appendToggle(p); 113 | 114 | assert(res == TD::OP_ParAppendResult::Success); 115 | } 116 | 117 | { 118 | TD::OP_NumericParameter p; 119 | p.name = MinimumdistanceName; 120 | p.label = MinimumdistanceLabel; 121 | p.page = "Sprinkle"; 122 | p.defaultValues[0] = 0.01; 123 | p.minSliders[0] = 0.0; 124 | p.maxSliders[0] = 1.0; 125 | p.minValues[0] = 0.0; 126 | p.maxValues[0] = 1.0; 127 | p.clampMins[0] = true; 128 | p.clampMaxes[0] = false; 129 | TD::OP_ParAppendResult res = manager->appendFloat(p); 130 | 131 | assert(res == TD::OP_ParAppendResult::Success); 132 | } 133 | 134 | 135 | } 136 | 137 | #pragma endregion -------------------------------------------------------------------------------- /SOP/SprinkleSOP/Parameters.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | class TD::OP_Inputs; 6 | class TD::OP_ParameterManager; 7 | 8 | #pragma region ParNames and ParLabels 9 | 10 | // Names of the parameters 11 | 12 | constexpr static char SeedName[] = "Seed"; 13 | constexpr static char SeedLabel[] = "Seed"; 14 | 15 | constexpr static char GenerateName[] = "Generate"; 16 | constexpr static char GenerateLabel[] = "Generate"; 17 | 18 | constexpr static char PointcountName[] = "Pointcount"; 19 | constexpr static char PointcountLabel[] = "Point Count"; 20 | 21 | constexpr static char SeparatepointsName[] = "Separatepoints"; 22 | constexpr static char SeparatepointsLabel[] = "Separate Points"; 23 | 24 | constexpr static char MinimumdistanceName[] = "Minimumdistance"; 25 | constexpr static char MinimumdistanceLabel[] = "Minimum Distance"; 26 | 27 | 28 | #pragma endregion 29 | 30 | #pragma region Menus 31 | enum class GenerateMenuItems 32 | { 33 | Area, 34 | Primitive, 35 | Boundingbox, 36 | Volume 37 | }; 38 | 39 | #pragma endregion 40 | 41 | 42 | #pragma region Parameters 43 | class Parameters 44 | { 45 | public: 46 | static void setup(TD::OP_ParameterManager*); 47 | 48 | // Seed 49 | static double evalSeed(const TD::OP_Inputs* inputs); 50 | 51 | // Generate 52 | static GenerateMenuItems evalGenerate(const TD::OP_Inputs* inputs); 53 | 54 | // Point Count 55 | static int evalPointcount(const TD::OP_Inputs* inputs); 56 | 57 | // Separate Points 58 | static bool evalSeparatepoints(const TD::OP_Inputs* inputs); 59 | 60 | // Minimum Distance 61 | static double evalMinimumdistance(const TD::OP_Inputs* inputs); 62 | 63 | 64 | }; 65 | #pragma endregion -------------------------------------------------------------------------------- /SOP/SprinkleSOP/README.md: -------------------------------------------------------------------------------- 1 | # Sprinkle SOP 2 | This is a proof of concept version of the now builtin TouchDesigner Sprinkle SOP. The Sprinkle SOP is used to add points to either the surface or the volume of a SOP. You can create points on a surface, or within a closed volume based on the Method menu. The Surface method keeps the distribution of points constant per unit area of surface, whereas Per-Primitive gives each primitive, usually triangles, a constant number per primitive no matter their size. 3 | 4 | ## Parameters 5 | * **Seed** - Any number, integer or non-integer, which starts the random number generator. Each number gives completely different point positions. 6 | * **Generate** - Describes where points are located. 7 | * **Surface Area** - Points are evenly distributed along the entire surface of the geometry. That is, smaller polygons receives fewer points on average than larger polygons, etc. 8 | * **Per Primitive** - Points are distributed equally amongst each primitive. That is, each polygon receives the same number of points. 9 | * **Bounding Box** - Points are distributed within the bounding box volume of the geometry. This can be faster, though less accurate than the volume method. 10 | * **Inside Volume** - Points are evenly distributed within the entire volume of the geometry. 11 | * **Point Count** - The total number of points created. 12 | * **Separate Points** - Remove points until remaining are a minimum distance apart. 13 | * **Minimum Distance** - Minimum distance when using Consolidate option. 14 | -------------------------------------------------------------------------------- /SOP/SprinkleSOP/RandomPointsBuffer.cpp: -------------------------------------------------------------------------------- 1 | #include "RandomPointsBuffer.h" 2 | 3 | #include "CPlusPlus_Common.h" 4 | #include 5 | 6 | using namespace TD; 7 | 8 | enum class Axis 9 | { 10 | X = 0, 11 | Y = 1, 12 | Z = 2 13 | }; 14 | 15 | namespace 16 | { 17 | double dist(const Position& A, const Position& B) 18 | { 19 | Vector AB{ B.x - A.x, B.y - A.y, B.z - A.z }; 20 | return AB.length(); 21 | } 22 | } 23 | 24 | class Node 25 | { 26 | public: 27 | Node(size_t pos) : left{ nullptr }, right{ nullptr }, index{ pos } 28 | { 29 | } 30 | 31 | ~Node() 32 | { 33 | delete left; 34 | delete right; 35 | } 36 | 37 | void 38 | addPoint(std::vector& pts, const Position& pos, int axis) 39 | { 40 | double newVal; 41 | double curVal; 42 | 43 | switch (static_cast(axis)) 44 | { 45 | default: 46 | case Axis::X: 47 | newVal = pos.x; 48 | curVal = pts.at(index).x; 49 | break; 50 | case Axis::Y: 51 | newVal = pos.y; 52 | curVal = pts.at(index).y; 53 | break; 54 | case Axis::Z: 55 | newVal = pos.z; 56 | curVal = pts.at(index).z; 57 | break; 58 | } 59 | 60 | Node** next; 61 | if (newVal < curVal) 62 | next = &right; 63 | else 64 | next = &left; 65 | 66 | if (*next) 67 | { 68 | (*next)->addPoint(pts, pos, (axis + 1) % 3); 69 | } 70 | else 71 | { 72 | *next = new Node(pts.size()); 73 | pts.push_back(pos); 74 | } 75 | } 76 | 77 | void 78 | nearestNeighborDist(std::vector& pts, const Position& pos, const double& constraint , int axis, double& minDist) 79 | { 80 | double newVal; 81 | double curVal; 82 | 83 | switch (static_cast(axis)) 84 | { 85 | default: 86 | case Axis::X: 87 | newVal = pos.x; 88 | curVal = pts.at(index).x; 89 | break; 90 | case Axis::Y: 91 | newVal = pos.y; 92 | curVal = pts.at(index).y; 93 | break; 94 | case Axis::Z: 95 | newVal = pos.z; 96 | curVal = pts.at(index).z; 97 | break; 98 | } 99 | 100 | double planeDist = std::fabs(newVal - curVal); 101 | minDist = std::min(minDist, dist(pos, pts.at(index))); 102 | 103 | Node* next; 104 | Node* other; 105 | 106 | if (newVal < curVal) 107 | { 108 | next = right; 109 | other = left; 110 | } 111 | else 112 | { 113 | next = left; 114 | other = right; 115 | } 116 | 117 | if (minDist < constraint) 118 | return; 119 | 120 | if (planeDist < constraint && other) 121 | { 122 | other->nearestNeighborDist(pts, pos, constraint, (axis + 1) % 3, minDist); 123 | } 124 | 125 | if (next) 126 | { 127 | next->nearestNeighborDist(pts, pos, constraint, (axis + 1) % 3, minDist); 128 | } 129 | } 130 | 131 | Node* left; 132 | Node* right; 133 | size_t index; 134 | }; 135 | 136 | RandomPointsBuffer::RandomPointsBuffer(bool separatePoints, double distance) : 137 | root{ nullptr }, mySeparatePoints{ separatePoints }, myDistance{ distance } 138 | { 139 | } 140 | 141 | 142 | RandomPointsBuffer::~RandomPointsBuffer() 143 | { 144 | delete root; 145 | points.clear(); 146 | } 147 | 148 | bool 149 | RandomPointsBuffer::addIfPointFits(const Position& p) 150 | { 151 | if (mySeparatePoints) 152 | { 153 | if (doesPointFit(p)) 154 | { 155 | addPoint(p); 156 | return true; 157 | } 158 | } 159 | else 160 | { 161 | points.push_back(p); 162 | return true; 163 | } 164 | 165 | return false; 166 | } 167 | 168 | std::vector& 169 | RandomPointsBuffer::getVector() 170 | { 171 | return points; 172 | } 173 | 174 | void RandomPointsBuffer::addPoint(const Position& p) 175 | { 176 | if (!root) 177 | { 178 | root = new Node(0); 179 | points.push_back(p); 180 | } 181 | else 182 | { 183 | root->addPoint(points, p, static_cast(Axis::X)); 184 | } 185 | } 186 | 187 | bool 188 | RandomPointsBuffer::doesPointFit(const Position& p) 189 | { 190 | if (!root) 191 | return true; 192 | 193 | double distance = dist(p, points.front()); 194 | root->nearestNeighborDist(points, p, myDistance, static_cast(Axis::X), distance); 195 | return distance > myDistance; 196 | } 197 | -------------------------------------------------------------------------------- /SOP/SprinkleSOP/RandomPointsBuffer.h: -------------------------------------------------------------------------------- 1 | #ifndef __MinDistanceTree__ 2 | #define __MinDistanceTree__ 3 | 4 | #include 5 | #include "CPlusPlus_Common.h" 6 | 7 | class TD::Position; 8 | class Node; 9 | 10 | class RandomPointsBuffer 11 | { 12 | public: 13 | RandomPointsBuffer(bool separatePoints, double distance); 14 | 15 | ~RandomPointsBuffer(); 16 | 17 | bool addIfPointFits(const TD::Position&); 18 | 19 | std::vector& getVector(); 20 | 21 | private: 22 | void addPoint(const TD::Position&); 23 | 24 | bool doesPointFit(const TD::Position&); 25 | 26 | Node* root; 27 | std::vector points; 28 | bool mySeparatePoints; 29 | double myDistance; 30 | }; 31 | 32 | #endif 33 | -------------------------------------------------------------------------------- /SOP/SprinkleSOP/SprinkleSOP.h: -------------------------------------------------------------------------------- 1 | /* Shared Use License: This file is owned by Derivative Inc. (Derivative) 2 | * and can only be used, and/or modified for use, in conjunction with 3 | * Derivative's TouchDesigner software, and only if you are a licensee who has 4 | * accepted Derivative's TouchDesigner license or assignment agreement 5 | * (which also govern the use of this file). You may share or redistribute 6 | * a modified version of this file provided the following conditions are met: 7 | * 8 | * 1. The shared file or redistribution must retain the information set out 9 | * above and this list of conditions. 10 | * 2. Derivative's name (Derivative Inc.) or its trademarks may not be used 11 | * to endorse or promote products derived from this file without specific 12 | * prior written permission from Derivative. 13 | */ 14 | 15 | #ifndef __SprinkleSOP__ 16 | #define __SprinkleSOP__ 17 | 18 | #include "SOP_CPlusPlusBase.h" 19 | #include "Parameters.h" 20 | 21 | #include 22 | #include 23 | #include 24 | #include 25 | 26 | class RandomPointsBuffer; 27 | class VolSprinkleTree; 28 | 29 | /* 30 | This example implements a SOP which outputs random points given a mesh and the following 31 | parameters: 32 | - Seed: A number to start the random number generator. 33 | - Generate: One of [Surface Area, Per Primitive, Bounding Box, Inside Volume] which 34 | determines how to generate the points. Surface Area will generate points evenly on the 35 | surface of the mesh. Per Primitive, will generate points evenly distributed among primitives. 36 | Inside Bounding Box, will generate inside the bounding box of the geometry. Inside Volume, will 37 | generate points inside the geometry. 38 | - Point Count: The total number of points to generate. 39 | - Separate Points: If On, it will separate the points so the distance between the points 40 | is at least the parameter Minimum Distance. 41 | - Minimum Distance: The distance between each random point generated. 42 | 43 | This SOP takes one to two inputs: 44 | - The reference geometry where the SOP will generate points. 45 | - If Generate is [Surface Area, Per Primitive], the points generated along input 1 will be mapped 46 | to the surface of this input. It must be the same geometry as input 2, this input is used for animating 47 | the generated points. 48 | 49 | Note, if Generate is [Surface Area, Per Primitive] a point float attribute named Surface will be setted with values 50 | [primNumber, r1, r2] where r1, r2 are uniform random numbers from 0 to 1. 51 | */ 52 | 53 | // Check methods [getNumInfoCHOPChans, getInfoCHOPChan, getInfoDATSize, getInfoDATEntries] 54 | // if you want to output values to the Info CHOP/DAT 55 | 56 | // To get more help about these functions, look at SOP_CPlusPlusBase.h 57 | class SprinkleSOP : public TD::SOP_CPlusPlusBase 58 | { 59 | public: 60 | SprinkleSOP(const TD::OP_NodeInfo* info); 61 | virtual ~SprinkleSOP(); 62 | 63 | virtual void getGeneralInfo(TD::SOP_GeneralInfo*, const TD::OP_Inputs*, void*) override; 64 | 65 | virtual void execute(TD::SOP_Output*, const TD::OP_Inputs*, void*) override; 66 | 67 | virtual void executeVBO(TD::SOP_VBOOutput*, const TD::OP_Inputs*, void*) override; 68 | 69 | virtual void setupParameters(TD::OP_ParameterManager*, void*) override; 70 | 71 | virtual void getErrorString(TD::OP_String*, void*) override; 72 | 73 | private: 74 | void executeAreaScatter(const TD::OP_SOPInput*); 75 | 76 | void executePrimScatter(const TD::OP_SOPInput*); 77 | 78 | void executeVolumeScatter(const TD::OP_SOPInput*); 79 | 80 | void executeBoundingBoxScatter(const TD::OP_SOPInput*); 81 | 82 | std::vector mapSurfaceToSOP(const TD::OP_SOPInput*); 83 | 84 | bool addPointToPrim(const TD::Position*, const TD::SOP_PrimitiveInfo* prims, size_t primN); 85 | 86 | bool addPointToBoundingBox(TD::BoundingBox&); 87 | 88 | TD::Position getPointInBoundingBox(TD::BoundingBox&); 89 | 90 | bool addPointToVolume(const TD::OP_SOPInput*, TD::BoundingBox&); 91 | 92 | int myPointCount; 93 | int64_t myInputCook; 94 | std::mt19937 myRNG; 95 | std::string myError; 96 | 97 | RandomPointsBuffer* myPoints; 98 | VolSprinkleTree* myVolSprinkleTree; 99 | std::vector mySurfaceAttribute; 100 | 101 | Parameters myParms; 102 | }; 103 | 104 | #endif // !__SprinkleSOP__ 105 | -------------------------------------------------------------------------------- /SOP/SprinkleSOP/SprinkleSOP.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio Version 16 4 | VisualStudioVersion = 16.0.30011.22 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "SprinkleSOP", "SprinkleSOP.vcxproj", "{3F5BEECD-FA36-459F-91B8-BB481A67EF44}" 7 | EndProject 8 | Global 9 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 10 | Debug|x64 = Debug|x64 11 | Release|x64 = Release|x64 12 | EndGlobalSection 13 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 14 | {3F5BEECD-FA36-459F-91B8-BB481A67EF44}.Debug|x64.ActiveCfg = Debug|x64 15 | {3F5BEECD-FA36-459F-91B8-BB481A67EF44}.Debug|x64.Build.0 = Debug|x64 16 | {3F5BEECD-FA36-459F-91B8-BB481A67EF44}.Release|x64.ActiveCfg = Release|x64 17 | {3F5BEECD-FA36-459F-91B8-BB481A67EF44}.Release|x64.Build.0 = Release|x64 18 | EndGlobalSection 19 | GlobalSection(SolutionProperties) = preSolution 20 | HideSolutionNode = FALSE 21 | EndGlobalSection 22 | GlobalSection(ExtensibilityGlobals) = postSolution 23 | SolutionGuid = {CDCA304D-7173-47CC-BC43-257E4444266C} 24 | EndGlobalSection 25 | EndGlobal 26 | -------------------------------------------------------------------------------- /SOP/SprinkleSOP/VolSprinkleTree.cpp: -------------------------------------------------------------------------------- 1 | /* Shared Use License: This file is owned by Derivative Inc. (Derivative) 2 | * and can only be used, and/or modified for use, in conjunction with 3 | * Derivative's TouchDesigner software, and only if you are a licensee who has 4 | * accepted Derivative's TouchDesigner license or assignment agreement 5 | * (which also govern the use of this file). You may share or redistribute 6 | * a modified version of this file provided the following conditions are met: 7 | * 8 | * 1. The shared file or redistribution must retain the information set out 9 | * above and this list of conditions. 10 | * 2. Derivative's name (Derivative Inc.) or its trademarks may not be used 11 | * to endorse or promote products derived from this file without specific 12 | * prior written permission from Derivative. 13 | */ 14 | 15 | #include "VolSprinkleTree.h" 16 | #include "CPlusPlus_Common.h" 17 | #include "SOP_CPlusPlusBase.h" 18 | #include 19 | #include 20 | 21 | using namespace TD; 22 | 23 | namespace 24 | { 25 | float getVolume(BoundingBox& bb) 26 | { 27 | return bb.sizeX() * bb.sizeY() * bb.sizeZ(); 28 | } 29 | 30 | Position pointInBox(BoundingBox& bb, float r1, float r2, float r3) 31 | { 32 | Position p; 33 | p.x = r1 * bb.sizeX() + bb.minX; 34 | p.y = r2 * bb.sizeY() + bb.minY; 35 | p.z = r3 * bb.sizeZ() + bb.minZ; 36 | return p; 37 | } 38 | } 39 | 40 | struct BoxNode 41 | { 42 | BoxNode(BoundingBox& bb) : box{ bb }, cumulativeVolume{} 43 | { 44 | } 45 | BoxNode(Position& min, Position& max) : box{ min, max }, cumulativeVolume{} 46 | { 47 | } 48 | 49 | operator float() const { return cumulativeVolume; } 50 | 51 | BoundingBox box; 52 | float cumulativeVolume; 53 | }; 54 | 55 | VolSprinkleTree::VolSprinkleTree(const TD::OP_SOPInput* sop, BoundingBox& bb) 56 | { 57 | float boxSize = std::cbrt(getVolume(bb) / myBoxNumber); 58 | Vector boxSizeV = Vector{ boxSize, boxSize, boxSize }; 59 | 60 | for (float x = bb.minX; x < bb.maxX; x += boxSize) 61 | { 62 | for (float y = bb.minY; y < bb.maxY; y += boxSize) 63 | { 64 | for (float z = bb.minZ; z < bb.maxZ; z += boxSize) 65 | { 66 | Position origin = Position(x, y, z); 67 | processBox(BoundingBox(origin, origin + boxSizeV), sop); 68 | } 69 | } 70 | } 71 | 72 | if (myTree.empty()) 73 | myTree.emplace_back(BoxNode(bb)); 74 | 75 | float volume = 0.0; 76 | for (BoxNode& bn : myTree) 77 | { 78 | volume += getVolume(bn.box); 79 | bn.cumulativeVolume = volume; 80 | } 81 | } 82 | 83 | VolSprinkleTree::~VolSprinkleTree() 84 | { 85 | } 86 | 87 | Position 88 | VolSprinkleTree::getPoint(float r1, float r2, float r3, float r4) 89 | { 90 | float target = r1 * myTree.back().cumulativeVolume; 91 | auto it = std::upper_bound(myTree.begin(), myTree.end(), target); 92 | return pointInBox(it->box, r2, r3, r4); 93 | } 94 | 95 | void 96 | VolSprinkleTree::processBox(BoundingBox& bb, const TD::OP_SOPInput* sop) 97 | { 98 | Position p; 99 | 100 | bb.getCenter(&p); 101 | if (((TD::OP_SOPInput*)sop)->isInside(p)) 102 | { 103 | myTree.emplace_back(BoxNode(bb)); 104 | return; 105 | } 106 | } 107 | 108 | void VolSprinkleTree::outputTest(TD::SOP_Output* out) 109 | { 110 | auto outputBox = [&](BoundingBox& bb) { 111 | int idx = out->getNumPoints(); 112 | Position points[] = { 113 | Position(bb.minX, bb.minY, bb.minZ), 114 | Position(bb.minX, bb.maxY, bb.minZ), 115 | Position(bb.minX, bb.minY, bb.maxZ), 116 | Position(bb.minX, bb.maxY, bb.maxZ), 117 | Position(bb.maxX, bb.minY, bb.maxZ), 118 | Position(bb.maxX, bb.maxY, bb.maxZ), 119 | Position(bb.maxX, bb.minY, bb.minZ), 120 | Position(bb.maxX, bb.maxY, bb.minZ) }; 121 | out->addPoints(points, 8); 122 | int32_t primpoints[] = { 123 | idx, idx + 1, idx + 2, 124 | idx + 1, idx + 2, idx + 3, 125 | idx + 2, idx + 3, idx + 4, 126 | idx + 3, idx + 4, idx + 5, 127 | idx + 4, idx + 5, idx + 6, 128 | idx + 5, idx + 6, idx + 7, 129 | idx + 6, idx + 7, idx, 130 | idx + 7, idx, idx + 1, 131 | idx, idx + 2, idx + 6, 132 | idx + 2, idx + 4, idx + 6, 133 | idx + 1, idx + 3, idx + 5, 134 | idx + 1, idx + 5, idx + 7 135 | }; 136 | out->addTriangles(primpoints, 12); 137 | }; 138 | 139 | for (BoxNode& bn : myTree) 140 | { 141 | outputBox(bn.box); 142 | } 143 | } 144 | -------------------------------------------------------------------------------- /SOP/SprinkleSOP/VolSprinkleTree.h: -------------------------------------------------------------------------------- 1 | /* Shared Use License: This file is owned by Derivative Inc. (Derivative) 2 | * and can only be used, and/or modified for use, in conjunction with 3 | * Derivative's TouchDesigner software, and only if you are a licensee who has 4 | * accepted Derivative's TouchDesigner license or assignment agreement 5 | * (which also govern the use of this file). You may share or redistribute 6 | * a modified version of this file provided the following conditions are met: 7 | * 8 | * 1. The shared file or redistribution must retain the information set out 9 | * above and this list of conditions. 10 | * 2. Derivative's name (Derivative Inc.) or its trademarks may not be used 11 | * to endorse or promote products derived from this file without specific 12 | * prior written permission from Derivative. 13 | */ 14 | 15 | #ifndef __VolSprinkleTree__ 16 | #define __VolSprinkleTree__ 17 | 18 | #include 19 | #include 20 | #include "CPlusPlus_Common.h" 21 | #include "SOP_CPlusPlusBase.h" 22 | 23 | class TD::SOP_Output; 24 | 25 | struct BoxNode; 26 | 27 | class VolSprinkleTree 28 | { 29 | public: 30 | VolSprinkleTree(const TD::OP_SOPInput* sop, TD::BoundingBox& bb); 31 | ~VolSprinkleTree(); 32 | 33 | TD::Position getPoint(float, float, float, float); 34 | 35 | void outputTest(TD::SOP_Output*); 36 | private: 37 | constexpr static int myBoxNumber = 50000; 38 | 39 | void processBox(TD::BoundingBox&, const TD::OP_SOPInput*); 40 | 41 | std::vector myTree; 42 | std::mt19937 myRNG; 43 | }; 44 | 45 | #endif 46 | -------------------------------------------------------------------------------- /SOP/WrapPointsSOP/GL_Extensions.h: -------------------------------------------------------------------------------- 1 | // Stub file for simpler CHOP usage than an OpenGLTOP 2 | 3 | #include 4 | -------------------------------------------------------------------------------- /SOP/WrapPointsSOP/Parameters.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | class TD::OP_Inputs; 6 | class TD::OP_ParameterManager; 7 | 8 | #pragma region ParNames and ParLabels 9 | 10 | // Names of the parameters 11 | 12 | constexpr static char RaysName[] = "Rays"; 13 | constexpr static char RaysLabel[] = "Rays"; 14 | 15 | constexpr static char DirectionName[] = "Direction"; 16 | constexpr static char DirectionLabel[] = "Direction"; 17 | 18 | constexpr static char DestinationName[] = "Destination"; 19 | constexpr static char DestinationLabel[] = "Destination"; 20 | 21 | constexpr static char ReverseName[] = "Reverse"; 22 | constexpr static char ReverseLabel[] = "Reverse"; 23 | 24 | constexpr static char HitcolorName[] = "Hitcolor"; 25 | constexpr static char HitcolorLabel[] = "Hit Color"; 26 | 27 | constexpr static char MisscolorName[] = "Misscolor"; 28 | constexpr static char MisscolorLabel[] = "Miss Color"; 29 | 30 | constexpr static char ScaleName[] = "Scale"; 31 | constexpr static char ScaleLabel[] = "Scale"; 32 | 33 | 34 | #pragma endregion 35 | 36 | #pragma region Menus 37 | enum class RaysMenuItems 38 | { 39 | Parallel, 40 | Radial 41 | }; 42 | 43 | #pragma endregion 44 | 45 | 46 | #pragma region Parameters 47 | class Parameters 48 | { 49 | public: 50 | static void setup(TD::OP_ParameterManager*); 51 | 52 | // Rays 53 | static RaysMenuItems evalRays(const TD::OP_Inputs* inputs); 54 | 55 | // Direction 56 | static std::array evalDirection(const TD::OP_Inputs* inputs); 57 | 58 | // Destination 59 | static std::array evalDestination(const TD::OP_Inputs* inputs); 60 | 61 | // Reverse 62 | static bool evalReverse(const TD::OP_Inputs* inputs); 63 | 64 | // Hit Color 65 | static TD::Color evalHitcolor(const TD::OP_Inputs* inputs); 66 | 67 | // Miss Color 68 | static TD::Color evalMisscolor(const TD::OP_Inputs* inputs); 69 | 70 | // Scale 71 | static double evalScale(const TD::OP_Inputs* inputs); 72 | 73 | 74 | }; 75 | #pragma endregion -------------------------------------------------------------------------------- /SOP/WrapPointsSOP/README.md: -------------------------------------------------------------------------------- 1 | # Wrap Points SOP 2 | 3 | This example implements a SOP which uses sendRay to wrap input 1 to input 2. 4 | 5 | ## Parameters 6 | * **Rays**: One of [Parallel, Radial], which determines in which way the rays are sent. 7 | * **Direction**: If Rays is Parallel, it will send rays from the points of input 1 in this vector's direction. 8 | * **Destination**: If Rays is Radial, it will send rays from the points of input 1 towards this destination. 9 | * **Reverse**: If On, reverses the direction in which the rays are sent. 10 | * **Hit Color**: Which color to set those points that hit input 2. 11 | * **Miss Color**: Which color to set those points that did not hit input 2. 12 | * **Scale**: A scale for hitLength, 0 a hit point will stay in its original position; 1 a hit point will be at the location 13 | where it hit the second input. 14 | 15 | This SOP takes two inputs and wraps the first one onto the second one. -------------------------------------------------------------------------------- /SOP/WrapPointsSOP/WrapPointsSOP.h: -------------------------------------------------------------------------------- 1 | /* Shared Use License: This file is owned by Derivative Inc. (Derivative) 2 | * and can only be used, and/or modified for use, in conjunction with 3 | * Derivative's TouchDesigner software, and only if you are a licensee who has 4 | * accepted Derivative's TouchDesigner license or assignment agreement 5 | * (which also govern the use of this file). You may share or redistribute 6 | * a modified version of this file provided the following conditions are met: 7 | * 8 | * 1. The shared file or redistribution must retain the information set out 9 | * above and this list of conditions. 10 | * 2. Derivative's name (Derivative Inc.) or its trademarks may not be used 11 | * to endorse or promote products derived from this file without specific 12 | * prior written permission from Derivative. 13 | */ 14 | 15 | #ifndef __WrapPointsSOP__ 16 | #define __WrapPointsSOP__ 17 | 18 | #include "SOP_CPlusPlusBase.h" 19 | #include "CPlusPlus_Common.h" 20 | #include "Parameters.h" 21 | 22 | #include 23 | 24 | /* 25 | This example implements a SOP which uses sendRay to wrap input 1 to input 2. 26 | - Rays: One of [Parallel, Radial], which determines in which way the rays are sent. 27 | - Direction: If Rays is Parallel, it will send rays from the points of input 1 in this vector's direction. 28 | - Destination: If Rays is Radial, it will send rays from the points of input 1 towards this destination. 29 | - Reverse: If On, reverses the direction in which the rays are sent. 30 | - Hit Color: Which color to set those points that hit input 2. 31 | - Miss Color: Which color to set those points that did not hit input 2. 32 | - Scale: A scale for hitLength, 0 a hit point will stay in its original position; 1 a hit point will be at the location 33 | where it hit the second input. 34 | 35 | This SOP takes two inputs and wraps the first one onto the second one. 36 | */ 37 | 38 | // Check methods [getNumInfoCHOPChans, getInfoCHOPChan, getInfoDATSize, getInfoDATEntries] 39 | // if you want to output values to the Info CHOP/DAT 40 | 41 | // To get more help about these functions, look at SOP_CPlusPlusBase.h 42 | class WrapPointsSOP : public TD::SOP_CPlusPlusBase 43 | { 44 | public: 45 | WrapPointsSOP(const TD::OP_NodeInfo* info); 46 | virtual ~WrapPointsSOP(); 47 | 48 | virtual void getGeneralInfo(TD::SOP_GeneralInfo*, const TD::OP_Inputs*, void*) override; 49 | 50 | virtual void execute(TD::SOP_Output*, const TD::OP_Inputs*, void*) override; 51 | 52 | virtual void executeVBO(TD::SOP_VBOOutput*, const TD::OP_Inputs*, void*) override; 53 | 54 | virtual void setupParameters(TD::OP_ParameterManager*, void*) override; 55 | 56 | virtual void getWarningString(TD::OP_String*, void*) override; 57 | 58 | private: 59 | void castParallel(TD::SOP_Output*, const TD::OP_SOPInput*, const TD::OP_SOPInput*, TD::Vector, bool, double, TD::Color, TD::Color); 60 | 61 | void castRadial(TD::SOP_Output*, const TD::OP_SOPInput*, const TD::OP_SOPInput*, TD::Position, bool, double, TD::Color, TD::Color); 62 | 63 | // This method returns true if the input geometry only has triangles and lines 64 | void copyPrimitives(TD::SOP_Output*, const TD::OP_SOPInput*); 65 | 66 | // Before calling this functions SOP_Output should contain as many points as OP_SOPInput 67 | void copyAttributes(TD::SOP_Output*, const TD::OP_SOPInput*) const; 68 | 69 | void copyColors(TD::SOP_Output*, const TD::OP_SOPInput*) const; 70 | 71 | void copyTextures(TD::SOP_Output*, const TD::OP_SOPInput*) const; 72 | 73 | void copyCustomAttributes(TD::SOP_Output*, const TD::OP_SOPInput*) const; 74 | 75 | void castPoint(TD::SOP_Output*, const TD::Position*, const TD::Vector* normals, int index, const TD::OP_SOPInput* geo, TD::Vector direction, double, TD::Color, TD::Color); 76 | 77 | std::string myWarningString; 78 | 79 | Parameters myParms; 80 | }; 81 | 82 | #endif // !__WrapPointsSOP__ 83 | -------------------------------------------------------------------------------- /SOP/WrapPointsSOP/WrapPointsSOP.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio Version 16 4 | VisualStudioVersion = 16.0.30011.22 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "WrapPointsSOP", "WrapPointsSOP.vcxproj", "{3F5BEECD-FA36-459F-91B8-BB481A67EF44}" 7 | EndProject 8 | Global 9 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 10 | Debug|x64 = Debug|x64 11 | Release|x64 = Release|x64 12 | EndGlobalSection 13 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 14 | {3F5BEECD-FA36-459F-91B8-BB481A67EF44}.Debug|x64.ActiveCfg = Debug|x64 15 | {3F5BEECD-FA36-459F-91B8-BB481A67EF44}.Debug|x64.Build.0 = Debug|x64 16 | {3F5BEECD-FA36-459F-91B8-BB481A67EF44}.Release|x64.ActiveCfg = Release|x64 17 | {3F5BEECD-FA36-459F-91B8-BB481A67EF44}.Release|x64.Build.0 = Release|x64 18 | EndGlobalSection 19 | GlobalSection(SolutionProperties) = preSolution 20 | HideSolutionNode = FALSE 21 | EndGlobalSection 22 | GlobalSection(ExtensibilityGlobals) = postSolution 23 | SolutionGuid = {CDCA304D-7173-47CC-BC43-257E4444266C} 24 | EndGlobalSection 25 | EndGlobal 26 | -------------------------------------------------------------------------------- /TOP/BasicFilterTOP/BasicFilterTOP.h: -------------------------------------------------------------------------------- 1 | /* Shared Use License: This file is owned by Derivative Inc. (Derivative) 2 | * and can only be used, and/or modified for use, in conjunction with 3 | * Derivative's TouchDesigner software, and only if you are a licensee who has 4 | * accepted Derivative's TouchDesigner license or assignment agreement 5 | * (which also govern the use of this file). You may share or redistribute 6 | * a modified version of this file provided the following conditions are met: 7 | * 8 | * 1. The shared file or redistribution must retain the information set out 9 | * above and this list of conditions. 10 | * 2. Derivative's name (Derivative Inc.) or its trademarks may not be used 11 | * to endorse or promote products derived from this file without specific 12 | * prior written permission from Derivative. 13 | */ 14 | #ifndef __BasicFilterTOP__ 15 | #define __BasicFilterTOP__ 16 | 17 | #include "TOP_CPlusPlusBase.h" 18 | #include "Parameters.h" 19 | 20 | #include 21 | #include 22 | #include 23 | #include 24 | #include 25 | 26 | class ThreadManager; 27 | 28 | // for multithreading 29 | const int NumCPUPixelDatas = 3; 30 | 31 | using namespace TD; 32 | 33 | /* 34 | This example implements a TOP to limit the number of colors from the input. This example 35 | executes on CPU Memory and supports single threaded and multi threaded. 36 | It takes the following parameters: 37 | - Bits per Color: The number of bits for the RGB channels. Therefore, if 38 | we set this parameter to 1. We limit our color palette to 2^(3*1) = 8 colors. 39 | - Dither: If on, we apply a dithering algorithm to diffuse the error. 40 | - Multithreaded: If on, we calculate the output for 3 frames at the same time, therefore 41 | it lags from the input by 3/4 frames depending on Download Type. 42 | */ 43 | 44 | // Check methods [getNumInfoCHOPChans, getInfoCHOPChan, getInfoDATSize, getInfoDATEntries] 45 | // if you want to output values to the Info CHOP/DAT 46 | 47 | // To get more help about these functions, look at TOP_CPlusPlusBase.h 48 | class BasicFilterTOP : public TOP_CPlusPlusBase 49 | { 50 | public: 51 | BasicFilterTOP(const OP_NodeInfo *info, TOP_Context* context); 52 | virtual ~BasicFilterTOP(); 53 | 54 | virtual void getGeneralInfo(TOP_GeneralInfo*, const TD::OP_Inputs*, void* reserved) override; 55 | 56 | virtual void execute(TOP_Output*, const TD::OP_Inputs*, void* reserved) override; 57 | 58 | virtual void setupParameters(TD::OP_ParameterManager*, void* reserved) override; 59 | 60 | private: 61 | void switchToSingleThreaded(); 62 | 63 | void switchToMultiThreaded(); 64 | 65 | TOP_Context* myContext; 66 | OP_SmartRef myPrevDownRes; 67 | 68 | // Threading variables 69 | std::array myThreadManagers; 70 | std::queue myThreadQueue; 71 | int myExecuteCount; 72 | bool myMultiThreaded; 73 | Parameters myParms; 74 | }; 75 | 76 | #endif 77 | -------------------------------------------------------------------------------- /TOP/BasicFilterTOP/BasicFilterTOP.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio Version 16 4 | VisualStudioVersion = 16.0.30011.22 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "BasicFilterTOP", "BasicFilterTOP.vcxproj", "{3F5BEECD-FA36-459F-91B8-BB481A67EF44}" 7 | EndProject 8 | Global 9 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 10 | Debug|x64 = Debug|x64 11 | Release|x64 = Release|x64 12 | EndGlobalSection 13 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 14 | {3F5BEECD-FA36-459F-91B8-BB481A67EF44}.Debug|x64.ActiveCfg = Debug|x64 15 | {3F5BEECD-FA36-459F-91B8-BB481A67EF44}.Debug|x64.Build.0 = Debug|x64 16 | {3F5BEECD-FA36-459F-91B8-BB481A67EF44}.Release|x64.ActiveCfg = Release|x64 17 | {3F5BEECD-FA36-459F-91B8-BB481A67EF44}.Release|x64.Build.0 = Release|x64 18 | EndGlobalSection 19 | GlobalSection(SolutionProperties) = preSolution 20 | HideSolutionNode = FALSE 21 | EndGlobalSection 22 | GlobalSection(ExtensibilityGlobals) = postSolution 23 | SolutionGuid = {CDCA304D-7173-47CC-BC43-257E4444266C} 24 | EndGlobalSection 25 | EndGlobal 26 | -------------------------------------------------------------------------------- /TOP/BasicFilterTOP/FilterWork.cpp: -------------------------------------------------------------------------------- 1 | #include "FilterWork.h" 2 | // #include "Parameters.h" 3 | 4 | namespace 5 | { 6 | void 7 | diffuseError(uint32_t& pixel, uint32_t error, double coeff) 8 | { 9 | uint8_t* pxChan = reinterpret_cast(&pixel); 10 | uint8_t* eChan = reinterpret_cast(&error); 11 | 12 | for (int i = 0; i < 3; ++i) 13 | { 14 | double temp = pxChan[i] + coeff * eChan[i]; 15 | if (temp > UINT8_MAX) 16 | pxChan[i] = UINT8_MAX; 17 | else 18 | pxChan[i] = static_cast(temp); 19 | } 20 | } 21 | 22 | // This returns a buffer of pixels which the user should delete[] when its done using it 23 | uint32_t* 24 | resizeImage(uint32_t* inPixel, int inWidth, int inHeight, int outWidth, int outHeight) 25 | { 26 | uint32_t* ret = new uint32_t[outWidth * outHeight]; 27 | double scaleY = inWidth / static_cast(outWidth); 28 | double scaleX = inHeight / static_cast(outHeight); 29 | 30 | for (int y = 0; y < outHeight; ++y) 31 | { 32 | for (int x = 0; x < outWidth; ++x) 33 | { 34 | int inY = static_cast(y * scaleY); 35 | int inX = static_cast(x * scaleX); 36 | ret[y * outWidth + x] = inPixel[inY * inWidth + inX]; 37 | } 38 | } 39 | return ret; 40 | } 41 | 42 | uint32_t 43 | closestPaletteColor(uint32_t color, int colorBits) 44 | { 45 | uint8_t* channels = reinterpret_cast(&color); 46 | uint8_t outChannels[4]; 47 | const int shift = 8 - colorBits; 48 | 49 | for (int i = 0; i < 3; ++i) 50 | { 51 | outChannels[i] = (channels[i] >> shift) << shift; 52 | } 53 | outChannels[3] = channels[3]; 54 | 55 | return *reinterpret_cast(outChannels); 56 | } 57 | 58 | void 59 | doDithering(uint32_t* inPixel, uint32_t* outPixel, int w, int h, int colorBits) 60 | { 61 | for (int i = 0; i < h; ++i) 62 | { 63 | for (int j = 0; j < w; ++j) 64 | { 65 | uint32_t oldPx = inPixel[i * w + j]; 66 | uint32_t newPx = closestPaletteColor(oldPx, colorBits); 67 | uint32_t error = oldPx - newPx; 68 | outPixel[i * w + j] = newPx; 69 | 70 | if (j != w - 1) 71 | diffuseError(inPixel[i * w + j + 1], error, 7.0 / 16); 72 | if (j != 0 && i != h - 1) 73 | diffuseError(inPixel[(i + 1) * w + j - 1], error, 3.0 / 16); 74 | if (i != h - 1) 75 | diffuseError(inPixel[(i + 1) * w + 1], error, 5.0 / 16); 76 | if (j != w - 1 && i != h - 1) 77 | diffuseError(inPixel[(i + 1) * w + j + 1], error, 1.0 / 16); 78 | } 79 | } 80 | } 81 | 82 | void 83 | limitColors(uint32_t* inPixel, uint32_t* outPixel, int w, int h, int colorBits) 84 | { 85 | for (int i = 0; i < w * h; ++i) 86 | { 87 | outPixel[i] = closestPaletteColor(inPixel[i], colorBits); 88 | } 89 | } 90 | } 91 | 92 | 93 | void Filter::doFilterWork(uint32_t* inBuffer, int inWidth, int inHeight, uint32_t* outBuffer, int outWidth, int outHeight, bool doDither, int bitsPerColor) 94 | { 95 | bool needsResize = inHeight != outHeight || inWidth != outWidth; 96 | 97 | if (needsResize) 98 | { 99 | inBuffer = resizeImage(inBuffer, inWidth, inHeight, outWidth, outHeight); 100 | } 101 | 102 | if (doDither) 103 | doDithering(inBuffer, outBuffer, outWidth, outHeight, bitsPerColor); 104 | else 105 | limitColors(inBuffer, outBuffer, outWidth, outHeight, bitsPerColor); 106 | 107 | if (needsResize) 108 | { 109 | delete[] inBuffer; 110 | } 111 | } 112 | -------------------------------------------------------------------------------- /TOP/BasicFilterTOP/FilterWork.h: -------------------------------------------------------------------------------- 1 | #ifndef __FilterWork__ 2 | #define __FilterWork__ 3 | #include 4 | 5 | class OP_Inputs; 6 | class Parameters; 7 | 8 | namespace Filter 9 | { 10 | void doFilterWork(uint32_t* inBuffer, int inWidth, int inHeight, uint32_t* outBuffer, int outWidth, int outHeight, bool doDither, int bitsPerColor); 11 | } 12 | 13 | #endif // !__FilterWork__ 14 | 15 | -------------------------------------------------------------------------------- /TOP/BasicFilterTOP/Parameters.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include "CPlusPlus_Common.h" 4 | #include "Parameters.h" 5 | 6 | #pragma region Evals 7 | 8 | int 9 | Parameters::evalBitspercolor(const TD::OP_Inputs* inputs) 10 | { 11 | return inputs->getParInt(BitspercolorName); 12 | } 13 | 14 | bool 15 | Parameters::evalDither(const TD::OP_Inputs* inputs) 16 | { 17 | return inputs->getParInt(DitherName) ? true : false; 18 | } 19 | 20 | bool 21 | Parameters::evalMultithreaded(const TD::OP_Inputs* inputs) 22 | { 23 | return inputs->getParInt(MultithreadedName) ? true : false; 24 | } 25 | 26 | 27 | #pragma endregion 28 | 29 | #pragma region Setup 30 | 31 | void 32 | Parameters::setup(TD::OP_ParameterManager* manager) 33 | { 34 | { 35 | TD::OP_NumericParameter p; 36 | p.name = BitspercolorName; 37 | p.label = BitspercolorLabel; 38 | p.page = "Filter"; 39 | p.defaultValues[0] = 2; 40 | p.minSliders[0] = 1.0; 41 | p.maxSliders[0] = 8.0; 42 | p.minValues[0] = 1.0; 43 | p.maxValues[0] = 8.0; 44 | p.clampMins[0] = true; 45 | p.clampMaxes[0] = true; 46 | TD::OP_ParAppendResult res = manager->appendInt(p); 47 | 48 | assert(res == TD::OP_ParAppendResult::Success); 49 | } 50 | 51 | { 52 | TD::OP_NumericParameter p; 53 | p.name = DitherName; 54 | p.label = DitherLabel; 55 | p.page = "Filter"; 56 | p.defaultValues[0] = true; 57 | 58 | TD::OP_ParAppendResult res = manager->appendToggle(p); 59 | 60 | assert(res == TD::OP_ParAppendResult::Success); 61 | } 62 | 63 | { 64 | TD::OP_NumericParameter p; 65 | p.name = MultithreadedName; 66 | p.label = MultithreadedLabel; 67 | p.page = "Filter"; 68 | p.defaultValues[0] = false; 69 | 70 | TD::OP_ParAppendResult res = manager->appendToggle(p); 71 | 72 | assert(res == TD::OP_ParAppendResult::Success); 73 | } 74 | 75 | 76 | } 77 | 78 | #pragma endregion -------------------------------------------------------------------------------- /TOP/BasicFilterTOP/Parameters.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | class TD::OP_Inputs; 6 | class TD::OP_ParameterManager; 7 | 8 | #pragma region ParNames and ParLabels 9 | 10 | // Names of the parameters 11 | 12 | constexpr static char BitspercolorName[] = "Bitspercolor"; 13 | constexpr static char BitspercolorLabel[] = "Bits per Color"; 14 | 15 | constexpr static char DitherName[] = "Dither"; 16 | constexpr static char DitherLabel[] = "Dither"; 17 | 18 | constexpr static char MultithreadedName[] = "Multithreaded"; 19 | constexpr static char MultithreadedLabel[] = "Multithreaded"; 20 | 21 | 22 | #pragma endregion 23 | 24 | #pragma region Menus 25 | #pragma endregion 26 | 27 | 28 | #pragma region Parameters 29 | class Parameters 30 | { 31 | public: 32 | static void setup(TD::OP_ParameterManager*); 33 | 34 | // Bits per Color 35 | static int evalBitspercolor(const TD::OP_Inputs* inputs); 36 | 37 | // Dither 38 | static bool evalDither(const TD::OP_Inputs* inputs); 39 | 40 | // Multithreaded 41 | static bool evalMultithreaded(const TD::OP_Inputs* inputs); 42 | 43 | 44 | }; 45 | #pragma endregion -------------------------------------------------------------------------------- /TOP/BasicFilterTOP/README.md: -------------------------------------------------------------------------------- 1 | # Filter TOP 2 | 3 | This example implements a TOP to limit the number of colors from the input. This example 4 | executes on CPU Memory and supports single threaded and multi threaded. 5 | 6 | ## Parameters 7 | * **Bits per Color:** The number of bits for the RGB channels. Therefore, if 8 | we set this parameter to 1. We limit our color palette to 2^(3\*1) = 8 colors. 9 | * **Dither:** If on, we apply a dithering algorithm to diffuse the error. 10 | * **Multithreaded:** If on, we calculate the output for 3 frames at the same time, therefore 11 | it lags from the input by 3/4 frames depending on Download Type. -------------------------------------------------------------------------------- /TOP/BasicFilterTOP/ThreadManager.cpp: -------------------------------------------------------------------------------- 1 | #include "ThreadManager.h" 2 | 3 | #include "FilterWork.h" 4 | 5 | 6 | #include 7 | #include 8 | #include 9 | #include 10 | 11 | 12 | ThreadManager::ThreadManager() : 13 | myStatus{ ThreadStatus::Waiting }, myOutBuffer{nullptr}, myDownRes{nullptr}, 14 | myThread{}, myBufferMutex{}, myBufferCV{}, 15 | myThreadShouldExit{false}, myInWidth{}, myInHeight{}, 16 | myOutWidth{}, myOutHeight{}, myDoDither{ false }, myBitsPerColor{ 8 }, myContext{ nullptr }, myUploadInfo{} 17 | { 18 | myThread = new std::thread([this] { threadFn(); }); 19 | } 20 | 21 | 22 | ThreadManager::~ThreadManager() 23 | { 24 | myThreadShouldExit.store(true); 25 | myBufferCV.notify_all(); 26 | if (myThread->joinable()) 27 | { 28 | myThread->join(); 29 | } 30 | 31 | std::unique_lock bufferlock(myBufferMutex); 32 | if(myContext && myOutBuffer) 33 | myContext->returnBuffer(&myOutBuffer); 34 | bufferlock.unlock(); 35 | 36 | delete myThread; 37 | } 38 | 39 | void 40 | ThreadManager::sync(bool doDither, int bitsPerColor, int inWidth, int inHeight, 41 | const OP_SmartRef downRes, TD::TOP_Context* context) 42 | { 43 | std::unique_lock bufferlock(myBufferMutex); 44 | myDoDither = doDither; 45 | myBitsPerColor = bitsPerColor; 46 | myInWidth = inWidth; 47 | myInHeight = inHeight; 48 | 49 | myContext = context; 50 | myDownRes = downRes; 51 | myUploadInfo.textureDesc = myDownRes->textureDesc; 52 | myOutWidth = myUploadInfo.textureDesc.width; 53 | myOutHeight = myUploadInfo.textureDesc.height; 54 | myStatus.store(ThreadStatus::Ready); 55 | bufferlock.unlock(); 56 | 57 | myBufferCV.notify_all(); 58 | 59 | } 60 | 61 | 62 | void 63 | ThreadManager::threadFn() 64 | { 65 | while (!myThreadShouldExit) 66 | { 67 | std::unique_lock bufferLock(myBufferMutex); 68 | myBufferCV.wait(bufferLock, [this] { return myStatus.load() == ThreadStatus::Ready || myThreadShouldExit; }); 69 | if (myThreadShouldExit) 70 | { 71 | if (myDownRes) 72 | myDownRes.release(); 73 | return; 74 | } 75 | 76 | myStatus.store(ThreadStatus::Busy); 77 | 78 | const int outwidth = myOutWidth; 79 | const int outheight = myOutHeight; 80 | const int inwidth = myInWidth; 81 | const int inheight = myInHeight; 82 | const bool doDither = myDoDither; 83 | const int bitsPerColor = myBitsPerColor; 84 | TOP_Context* context = myContext; 85 | OP_SmartRef downRes = myDownRes; 86 | 87 | size_t byteSize = inwidth * inheight * sizeof(uint32_t); 88 | myOutBuffer = context->createOutputBuffer(byteSize, TOP_BufferFlags::None, nullptr); 89 | 90 | uint32_t* outbuf = (uint32_t*)myOutBuffer->data; 91 | 92 | 93 | uint32_t* inBuffer = (uint32_t*)downRes->getData(); 94 | 95 | Filter::doFilterWork(inBuffer, inwidth, inheight, outbuf, outwidth, outheight, doDither, bitsPerColor); 96 | myDownRes.release(); 97 | myStatus.store(ThreadStatus::Done); 98 | bufferLock.unlock(); 99 | 100 | myBufferCV.notify_one(); 101 | } 102 | } 103 | 104 | 105 | void 106 | ThreadManager::popOutBuffer(OP_SmartRef& outBuffer, TD::TOP_UploadInfo& info) 107 | { 108 | std::lock_guard bufferLock(myBufferMutex); 109 | outBuffer = std::move(myOutBuffer); 110 | info = std::move(myUploadInfo); 111 | myStatus.store(ThreadStatus::Waiting); 112 | } 113 | 114 | ThreadStatus 115 | ThreadManager::getStatus() 116 | { 117 | return myStatus.load(); 118 | } -------------------------------------------------------------------------------- /TOP/BasicFilterTOP/ThreadManager.h: -------------------------------------------------------------------------------- 1 | #ifndef __ThreadManager__ 2 | #define __ThreadManager__ 3 | 4 | #include "TOP_CPlusPlusBase.h" 5 | 6 | #include 7 | #include 8 | #include 9 | #include 10 | 11 | using namespace TD; 12 | 13 | // class Parameters; 14 | class OP_Inputs; 15 | 16 | 17 | enum class ThreadStatus 18 | { 19 | Busy, 20 | Ready, 21 | Done, 22 | Waiting 23 | }; 24 | 25 | class ThreadManager 26 | { 27 | public: 28 | ThreadManager(); 29 | 30 | ~ThreadManager(); 31 | 32 | void sync(bool doDither, int bitsPerColor, int inWidth, int inHeight, const OP_SmartRef downRes, TD::TOP_Context* context); 33 | 34 | 35 | void popOutBuffer(OP_SmartRef& outBuffer, TD::TOP_UploadInfo& info); 36 | 37 | ThreadStatus getStatus(); 38 | private: 39 | void threadFn(); 40 | 41 | std::atomic myStatus; 42 | 43 | // Out buffer resource 44 | OP_SmartRef myDownRes; 45 | OP_SmartRef myOutBuffer; 46 | 47 | // Thread and Sync variables 48 | std::thread* myThread; 49 | std::mutex myBufferMutex; 50 | std::condition_variable myBufferCV; 51 | std::atomic_bool myThreadShouldExit; 52 | 53 | // Parameters saved 54 | int myInWidth; 55 | int myInHeight; 56 | int myOutWidth; 57 | int myOutHeight; 58 | bool myDoDither; 59 | int myBitsPerColor; 60 | TD::TOP_Context* myContext; 61 | TD::TOP_UploadInfo myUploadInfo; 62 | }; 63 | 64 | #endif 65 | -------------------------------------------------------------------------------- /TOP/CannyEdgeTOP/CannyEdgeTOP.h: -------------------------------------------------------------------------------- 1 | /* Shared Use License: This file is owned by Derivative Inc. (Derivative) 2 | * and can only be used, and/or modified for use, in conjunction with 3 | * Derivative's TouchDesigner software, and only if you are a licensee who has 4 | * accepted Derivative's TouchDesigner license or assignment agreement 5 | * (which also govern the use of this file). You may share or redistribute 6 | * a modified version of this file provided the following conditions are met: 7 | * 8 | * 1. The shared file or redistribution must retain the information set out 9 | * above and this list of conditions. 10 | * 2. Derivative's name (Derivative Inc.) or its trademarks may not be used 11 | * to endorse or promote products derived from this file without specific 12 | * prior written permission from Derivative. 13 | */ 14 | 15 | #ifndef __CannyEdgeTOP__ 16 | #define __CannyEdgeTOP__ 17 | 18 | #include "TOP_CPlusPlusBase.h" 19 | #include "Parameters.h" 20 | 21 | #include 22 | #include 23 | 24 | namespace cv 25 | { 26 | namespace cuda 27 | { 28 | class GpuMat; 29 | } 30 | } 31 | 32 | namespace GpuUtils 33 | { 34 | enum class ChannelFormat; 35 | } 36 | 37 | /* 38 | This example implements a TOP exposing the canny edge detector using OpenCV's CUDA functionallity. 39 | 40 | It takes the following parameters: 41 | - Low Threshold: First threshold for the hysteresis procedure. 42 | - High Threshold: Second threshold for the hysteresis procedure. 43 | - Aperture size: Aperture size for the Sobel operator. 44 | - L2 Gradient: If On, a more accurate norm should be used to compute the image gradient. 45 | For more information visit: https://docs.opencv.org/3.4/d0/d05/group__cudaimgproc.html#gabc17953de36faa404acb07dc587451fc 46 | 47 | This TOP takes one input which must be 8 bit single channel. 48 | */ 49 | 50 | // To get more help about these functions, look at TOP_CPlusPlusBase.h 51 | class CannyEdgeTOP : public TD::TOP_CPlusPlusBase 52 | { 53 | public: 54 | CannyEdgeTOP(const TD::OP_NodeInfo *info, TD::TOP_Context *context); 55 | virtual ~CannyEdgeTOP(); 56 | 57 | virtual void getGeneralInfo(TD::TOP_GeneralInfo*, const TD::OP_Inputs*, void* reserved) override; 58 | 59 | virtual void execute(TD::TOP_Output*, const TD::OP_Inputs*, void* reserved) override; 60 | 61 | virtual void setupParameters(TD::OP_ParameterManager*, void* reserved) override; 62 | 63 | virtual void getErrorString(TD::OP_String*, void* reserved) override; 64 | 65 | private: 66 | bool checkInputTop(const TD::OP_TOPInput*); 67 | 68 | cv::cuda::GpuMat* myFrame; 69 | 70 | std::string myError; 71 | 72 | int myNumChan; 73 | int myMatType; 74 | int myPixelSize; 75 | 76 | TD::TOP_Context* myContext; 77 | cudaStream_t myStream; 78 | 79 | Parameters myParms; 80 | 81 | // In this example this value will be incremented each time the execute() 82 | // function is called, then passes back to the TOP 83 | int32_t myExecuteCount; 84 | }; 85 | 86 | #endif 87 | -------------------------------------------------------------------------------- /TOP/CannyEdgeTOP/CannyEdgeTOP.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio Version 16 4 | VisualStudioVersion = 16.0.30011.22 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "CannyEdgeTOP", "CannyEdgeTOP.vcxproj", "{3F5BEECD-FA36-459F-91B8-BB481A67EF44}" 7 | EndProject 8 | Global 9 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 10 | Debug|x64 = Debug|x64 11 | Release|x64 = Release|x64 12 | EndGlobalSection 13 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 14 | {3F5BEECD-FA36-459F-91B8-BB481A67EF44}.Debug|x64.ActiveCfg = Debug|x64 15 | {3F5BEECD-FA36-459F-91B8-BB481A67EF44}.Debug|x64.Build.0 = Debug|x64 16 | {3F5BEECD-FA36-459F-91B8-BB481A67EF44}.Release|x64.ActiveCfg = Release|x64 17 | {3F5BEECD-FA36-459F-91B8-BB481A67EF44}.Release|x64.Build.0 = Release|x64 18 | EndGlobalSection 19 | GlobalSection(SolutionProperties) = preSolution 20 | HideSolutionNode = FALSE 21 | EndGlobalSection 22 | GlobalSection(ExtensibilityGlobals) = postSolution 23 | SolutionGuid = {CDCA304D-7173-47CC-BC43-257E4444266C} 24 | EndGlobalSection 25 | EndGlobal 26 | -------------------------------------------------------------------------------- /TOP/CannyEdgeTOP/GpuUtils.cuh: -------------------------------------------------------------------------------- 1 | #ifndef __GPUUTILS__ 2 | #define __GPUUTILS__ 3 | 4 | struct cudaArray; 5 | namespace cv 6 | { 7 | namespace cuda 8 | { 9 | class GpuMat; 10 | } 11 | } 12 | 13 | namespace GpuUtils 14 | { 15 | enum class ChannelFormat 16 | { 17 | U8, 18 | U16, 19 | F16, 20 | F32 21 | }; 22 | 23 | void matGPUToArray(int width, int height, const cv::cuda::GpuMat& input, cudaArray* output, int pixelSize); 24 | 25 | void arrayToMatGPU(int width, int height, cudaArray* input, cv::cuda::GpuMat& output, int pixelSize); 26 | } 27 | #endif 28 | -------------------------------------------------------------------------------- /TOP/CannyEdgeTOP/Parameters.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include "CPlusPlus_Common.h" 4 | #include "Parameters.h" 5 | 6 | #pragma region Evals 7 | 8 | double 9 | Parameters::evalLowthreshold(const TD::OP_Inputs* inputs) 10 | { 11 | return inputs->getParDouble(LowthresholdName); 12 | } 13 | 14 | double 15 | Parameters::evalHighthreshold(const TD::OP_Inputs* inputs) 16 | { 17 | return inputs->getParDouble(HighthresholdName); 18 | } 19 | 20 | int 21 | Parameters::evalApperturesize(const TD::OP_Inputs* inputs) 22 | { 23 | return inputs->getParInt(ApperturesizeName); 24 | } 25 | 26 | bool 27 | Parameters::evalL2gradient(const TD::OP_Inputs* inputs) 28 | { 29 | return inputs->getParInt(L2gradientName) ? true : false; 30 | } 31 | 32 | 33 | #pragma endregion 34 | 35 | #pragma region Setup 36 | 37 | void 38 | Parameters::setup(TD::OP_ParameterManager* manager) 39 | { 40 | { 41 | TD::OP_NumericParameter p; 42 | p.name = LowthresholdName; 43 | p.label = LowthresholdLabel; 44 | p.page = "Edge Detector"; 45 | p.defaultValues[0] = 0.1; 46 | p.minSliders[0] = 0.0; 47 | p.maxSliders[0] = 1.0; 48 | p.minValues[0] = 0.0; 49 | p.maxValues[0] = 1.0; 50 | p.clampMins[0] = true; 51 | p.clampMaxes[0] = true; 52 | TD::OP_ParAppendResult res = manager->appendFloat(p); 53 | 54 | assert(res == TD::OP_ParAppendResult::Success); 55 | } 56 | 57 | { 58 | TD::OP_NumericParameter p; 59 | p.name = HighthresholdName; 60 | p.label = HighthresholdLabel; 61 | p.page = "Edge Detector"; 62 | p.defaultValues[0] = 0.9; 63 | p.minSliders[0] = 0.0; 64 | p.maxSliders[0] = 1.0; 65 | p.minValues[0] = 0.0; 66 | p.maxValues[0] = 1.0; 67 | p.clampMins[0] = true; 68 | p.clampMaxes[0] = true; 69 | TD::OP_ParAppendResult res = manager->appendFloat(p); 70 | 71 | assert(res == TD::OP_ParAppendResult::Success); 72 | } 73 | 74 | { 75 | TD::OP_NumericParameter p; 76 | p.name = ApperturesizeName; 77 | p.label = ApperturesizeLabel; 78 | p.page = "Edge Detector"; 79 | p.defaultValues[0] = 3; 80 | p.minSliders[0] = 1.0; 81 | p.maxSliders[0] = 31.0; 82 | p.minValues[0] = 1.0; 83 | p.maxValues[0] = 31.0; 84 | p.clampMins[0] = true; 85 | p.clampMaxes[0] = true; 86 | TD::OP_ParAppendResult res = manager->appendInt(p); 87 | 88 | assert(res == TD::OP_ParAppendResult::Success); 89 | } 90 | 91 | { 92 | TD::OP_NumericParameter p; 93 | p.name = L2gradientName; 94 | p.label = L2gradientLabel; 95 | p.page = "Edge Detector"; 96 | p.defaultValues[0] = false; 97 | 98 | TD::OP_ParAppendResult res = manager->appendToggle(p); 99 | 100 | assert(res == TD::OP_ParAppendResult::Success); 101 | } 102 | 103 | 104 | } 105 | 106 | #pragma endregion -------------------------------------------------------------------------------- /TOP/CannyEdgeTOP/Parameters.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | class TD::OP_Inputs; 6 | class TD::OP_ParameterManager; 7 | 8 | #pragma region ParNames and ParLabels 9 | 10 | // Names of the parameters 11 | 12 | constexpr static char LowthresholdName[] = "Lowthreshold"; 13 | constexpr static char LowthresholdLabel[] = "Low Threshold"; 14 | 15 | constexpr static char HighthresholdName[] = "Highthreshold"; 16 | constexpr static char HighthresholdLabel[] = "High Threshold"; 17 | 18 | constexpr static char ApperturesizeName[] = "Apperturesize"; 19 | constexpr static char ApperturesizeLabel[] = "Apperture Size"; 20 | 21 | constexpr static char L2gradientName[] = "L2gradient"; 22 | constexpr static char L2gradientLabel[] = "L2 Gradient"; 23 | 24 | 25 | #pragma endregion 26 | 27 | #pragma region Menus 28 | #pragma endregion 29 | 30 | 31 | #pragma region Parameters 32 | class Parameters 33 | { 34 | public: 35 | static void setup(TD::OP_ParameterManager*); 36 | 37 | // Low Threshold 38 | static double evalLowthreshold(const TD::OP_Inputs* inputs); 39 | 40 | // High Threshold 41 | static double evalHighthreshold(const TD::OP_Inputs* inputs); 42 | 43 | // Apperture Size 44 | static int evalApperturesize(const TD::OP_Inputs* inputs); 45 | 46 | // L2 Gradient 47 | static bool evalL2gradient(const TD::OP_Inputs* inputs); 48 | 49 | 50 | }; 51 | #pragma endregion -------------------------------------------------------------------------------- /TOP/CannyEdgeTOP/README.md: -------------------------------------------------------------------------------- 1 | # Canny Edge TOP 2 | 3 | This example implements a TOP exposing the canny edge detector using OpenCV's cuda functionallity. 4 | 5 | For more information visit: https://docs.opencv.org/3.4/d0/d05/group__cudaimgproc.html#gabc17953de36faa404acb07dc587451fc 6 | 7 | ## Prerequisites 8 | Requires a [reference](https://github.com/TouchDesigner/CustomOperatorSamples#referencing-opencv-libraries) to the OpenCV include and library folder. 9 | 10 | ## Parameters 11 | * **Low Threshold**: Minimum value for the intensity gradient to decide if it is used as a edge. 12 | * **High Threshold**: Maximum value for the intensity gradient to decide if it is used as a edge. 13 | * **Apperture Size**: Kernel size for the Sobel operator. 14 | * **L2 Gradient**: ndicating whether a more accurate L2 should be used to calculate the image gradient magnitude. 15 | 16 | This TOP takes one input which must be 8 bit single channel. 17 | -------------------------------------------------------------------------------- /TOP/DistanceTransformTOP/DistanceTransformTOP.h: -------------------------------------------------------------------------------- 1 | /* Shared Use License: This file is owned by Derivative Inc. (Derivative) 2 | * and can only be used, and/or modified for use, in conjunction with 3 | * Derivative's TouchDesigner software, and only if you are a licensee who has 4 | * accepted Derivative's TouchDesigner license or assignment agreement 5 | * (which also govern the use of this file). You may share or redistribute 6 | * a modified version of this file provided the following conditions are met: 7 | * 8 | * 1. The shared file or redistribution must retain the information set out 9 | * above and this list of conditions. 10 | * 2. Derivative's name (Derivative Inc.) or its trademarks may not be used 11 | * to endorse or promote products derived from this file without specific 12 | * prior written permission from Derivative. 13 | */ 14 | 15 | #ifndef __DistanceTransformTOP__ 16 | #define __DistanceTransformTOP__ 17 | 18 | #include "TOP_CPlusPlusBase.h" 19 | #include "Parameters.h" 20 | 21 | #include 22 | #include 23 | #include 24 | 25 | /* 26 | This example implements a TOP to calculate the distance transform using OpenCV. 27 | 28 | It takes the following parameters: 29 | - Distance Type: One of [L1, L2, C], which determines how to calculate the distance. 30 | - Mask Size: One of [3x3, 5x5, Precise], which determines the size of the transform mask. 31 | - Normalize: If On, normalize the output image. 32 | For more information visit: https://docs.opencv.org/3.4/d7/d1b/group__imgproc__misc.html#ga8a0b7fdfcb7a13dde018988ba3a43042 33 | 34 | This TOP takes one input which must be 8 bit single channel. 35 | */ 36 | 37 | // To get more help about these functions, look at TOP_CPlusPlusBase.h 38 | class DistanceTransformTOP : public TD::TOP_CPlusPlusBase 39 | { 40 | public: 41 | DistanceTransformTOP(const TD::OP_NodeInfo *info, TD::TOP_Context *context); 42 | virtual ~DistanceTransformTOP(); 43 | 44 | virtual void getGeneralInfo(TD::TOP_GeneralInfo*, const TD::OP_Inputs*, void* reserved) override; 45 | 46 | virtual void execute(TD::TOP_Output*, const TD::OP_Inputs*, void* reserved) override; 47 | 48 | virtual void setupParameters(TD::OP_ParameterManager*, void* reserved) override; 49 | 50 | private: 51 | void inputTopToMat(const TD::OP_Inputs*); 52 | 53 | void cvMatToOutput(TD::TOP_Output*, TD::TOP_UploadInfo) const; 54 | 55 | int getType(DistancetypeMenuItems dt) 56 | { 57 | switch (dt) 58 | { 59 | default: 60 | case DistancetypeMenuItems::L1: 61 | return cv::DIST_L1; 62 | case DistancetypeMenuItems::L2: 63 | return cv::DIST_L2; 64 | case DistancetypeMenuItems::C: 65 | return cv::DIST_C; 66 | } 67 | } 68 | 69 | int getMask(MasksizeMenuItems ms) 70 | { 71 | switch (ms) 72 | { 73 | default: 74 | case MasksizeMenuItems::Three: 75 | return cv::DIST_MASK_3; 76 | case MasksizeMenuItems::Five: 77 | return cv::DIST_MASK_5; 78 | case MasksizeMenuItems::Precise: 79 | return cv::DIST_MASK_PRECISE; 80 | } 81 | } 82 | 83 | cv::Mat* myFrame; 84 | int myExecuteCount; 85 | TD::TOP_Context* myContext; 86 | TD::OP_SmartRef myPrevDownRes; 87 | Parameters myParms; 88 | }; 89 | 90 | #endif 91 | -------------------------------------------------------------------------------- /TOP/DistanceTransformTOP/DistanceTransformTOP.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio Version 16 4 | VisualStudioVersion = 16.0.30011.22 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "DistanceTransformTOP", "DistanceTransformTOP.vcxproj", "{3F5BEECD-FA36-459F-91B8-BB481A67EF44}" 7 | EndProject 8 | Global 9 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 10 | Debug|x64 = Debug|x64 11 | Release|x64 = Release|x64 12 | EndGlobalSection 13 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 14 | {3F5BEECD-FA36-459F-91B8-BB481A67EF44}.Debug|x64.ActiveCfg = Debug|x64 15 | {3F5BEECD-FA36-459F-91B8-BB481A67EF44}.Debug|x64.Build.0 = Debug|x64 16 | {3F5BEECD-FA36-459F-91B8-BB481A67EF44}.Release|x64.ActiveCfg = Release|x64 17 | {3F5BEECD-FA36-459F-91B8-BB481A67EF44}.Release|x64.Build.0 = Release|x64 18 | EndGlobalSection 19 | GlobalSection(SolutionProperties) = preSolution 20 | HideSolutionNode = FALSE 21 | EndGlobalSection 22 | GlobalSection(ExtensibilityGlobals) = postSolution 23 | SolutionGuid = {CDCA304D-7173-47CC-BC43-257E4444266C} 24 | EndGlobalSection 25 | EndGlobal 26 | -------------------------------------------------------------------------------- /TOP/DistanceTransformTOP/Parameters.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include "CPlusPlus_Common.h" 4 | #include "Parameters.h" 5 | 6 | #pragma region Evals 7 | 8 | DistancetypeMenuItems 9 | Parameters::evalDistancetype(const TD::OP_Inputs* inputs) 10 | { 11 | return static_cast(inputs->getParInt(DistancetypeName)); 12 | } 13 | 14 | MasksizeMenuItems 15 | Parameters::evalMasksize(const TD::OP_Inputs* inputs) 16 | { 17 | return static_cast(inputs->getParInt(MasksizeName)); 18 | } 19 | 20 | bool 21 | Parameters::evalNormalize(const TD::OP_Inputs* inputs) 22 | { 23 | return inputs->getParInt(NormalizeName) ? true : false; 24 | } 25 | 26 | ChannelMenuItems 27 | Parameters::evalChannel(const TD::OP_Inputs* inputs) 28 | { 29 | return static_cast(inputs->getParInt(ChannelName)); 30 | } 31 | 32 | 33 | #pragma endregion 34 | 35 | #pragma region Setup 36 | 37 | void 38 | Parameters::setup(TD::OP_ParameterManager* manager) 39 | { 40 | { 41 | TD::OP_StringParameter p; 42 | p.name = DistancetypeName; 43 | p.label = DistancetypeLabel; 44 | p.page = "Transform"; 45 | p.defaultValue = "L1"; 46 | std::array Names = 47 | { 48 | "L1", 49 | "L2", 50 | "C" 51 | }; 52 | std::array Labels = 53 | { 54 | "L1", 55 | "L2", 56 | "C" 57 | }; 58 | TD::OP_ParAppendResult res = manager->appendMenu(p, Names.size(), Names.data(), Labels.data()); 59 | 60 | assert(res == TD::OP_ParAppendResult::Success); 61 | } 62 | 63 | { 64 | TD::OP_StringParameter p; 65 | p.name = MasksizeName; 66 | p.label = MasksizeLabel; 67 | p.page = "Transform"; 68 | p.defaultValue = "Three"; 69 | std::array Names = 70 | { 71 | "Three", 72 | "Five", 73 | "Precise" 74 | }; 75 | std::array Labels = 76 | { 77 | "3x3", 78 | "5x5", 79 | "Precise" 80 | }; 81 | TD::OP_ParAppendResult res = manager->appendMenu(p, Names.size(), Names.data(), Labels.data()); 82 | 83 | assert(res == TD::OP_ParAppendResult::Success); 84 | } 85 | 86 | { 87 | TD::OP_NumericParameter p; 88 | p.name = NormalizeName; 89 | p.label = NormalizeLabel; 90 | p.page = "Transform"; 91 | p.defaultValues[0] = false; 92 | 93 | TD::OP_ParAppendResult res = manager->appendToggle(p); 94 | 95 | assert(res == TD::OP_ParAppendResult::Success); 96 | } 97 | 98 | { 99 | TD::OP_StringParameter p; 100 | p.name = ChannelName; 101 | p.label = ChannelLabel; 102 | p.page = "Transform"; 103 | p.defaultValue = "R"; 104 | std::array Names = 105 | { 106 | "R", 107 | "G", 108 | "B", 109 | "A" 110 | }; 111 | std::array Labels = 112 | { 113 | "R", 114 | "G", 115 | "B", 116 | "A" 117 | }; 118 | TD::OP_ParAppendResult res = manager->appendMenu(p, Names.size(), Names.data(), Labels.data()); 119 | 120 | assert(res == TD::OP_ParAppendResult::Success); 121 | } 122 | 123 | 124 | } 125 | 126 | #pragma endregion -------------------------------------------------------------------------------- /TOP/DistanceTransformTOP/Parameters.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | class TD::OP_Inputs; 6 | class TD::OP_ParameterManager; 7 | 8 | #pragma region ParNames and ParLabels 9 | 10 | // Names of the parameters 11 | 12 | constexpr static char DistancetypeName[] = "Distancetype"; 13 | constexpr static char DistancetypeLabel[] = "Distance Type"; 14 | 15 | constexpr static char MasksizeName[] = "Masksize"; 16 | constexpr static char MasksizeLabel[] = "Mask Size"; 17 | 18 | constexpr static char NormalizeName[] = "Normalize"; 19 | constexpr static char NormalizeLabel[] = "Normalize"; 20 | 21 | constexpr static char ChannelName[] = "Channel"; 22 | constexpr static char ChannelLabel[] = "Channel"; 23 | 24 | 25 | #pragma endregion 26 | 27 | #pragma region Menus 28 | enum class DistancetypeMenuItems 29 | { 30 | L1, 31 | L2, 32 | C 33 | }; 34 | 35 | enum class MasksizeMenuItems 36 | { 37 | Three, 38 | Five, 39 | Precise 40 | }; 41 | 42 | enum class ChannelMenuItems 43 | { 44 | R, 45 | G, 46 | B, 47 | A 48 | }; 49 | 50 | #pragma endregion 51 | 52 | 53 | #pragma region Parameters 54 | class Parameters 55 | { 56 | public: 57 | static void setup(TD::OP_ParameterManager*); 58 | 59 | // Distance Type 60 | static DistancetypeMenuItems evalDistancetype(const TD::OP_Inputs* inputs); 61 | 62 | // Mask Size 63 | static MasksizeMenuItems evalMasksize(const TD::OP_Inputs* inputs); 64 | 65 | // Normalize 66 | static bool evalNormalize(const TD::OP_Inputs* inputs); 67 | 68 | // Channel 69 | static ChannelMenuItems evalChannel(const TD::OP_Inputs* inputs); 70 | 71 | 72 | }; 73 | #pragma endregion -------------------------------------------------------------------------------- /TOP/DistanceTransformTOP/README.md: -------------------------------------------------------------------------------- 1 | # Distance Transform TOP 2 | This example implements a TOP to calculate the distance transform using OpenCV. 3 | 4 | For more information visit: https://docs.opencv.org/3.4/d7/d1b/group__imgproc__misc.html#ga8a0b7fdfcb7a13dde018988ba3a43042 5 | 6 | ## Prerequisites 7 | Requires a [reference](https://github.com/TouchDesigner/CustomOperatorSamples#referencing-opencv-libraries) to the OpenCV include and library folder. 8 | 9 | ## Parameters 10 | * **Distance Type**: One of [L1, L2, C], which determines how to calculate the distance. 11 | * **Mask Size**: One of [3x3, 5x5, Precise], which determines the size of the transform mask. 12 | * **Normalize**: If On, normalize the output image. 13 | 14 | This TOP takes one input which must be 8 bit single channel. 15 | -------------------------------------------------------------------------------- /TOP/ONNXCandyStyleTOP/ONNXCandyStyleTOP.h: -------------------------------------------------------------------------------- 1 | /* Shared Use License: This file is owned by Derivative Inc. (Derivative) 2 | * and can only be used, and/or modified for use, in conjunction with 3 | * Derivative's TouchDesigner software, and only if you are a licensee who has 4 | * accepted Derivative's TouchDesigner license or assignment agreement 5 | * (which also govern the use of this file). You may share or redistribute 6 | * a modified version of this file provided the following conditions are met: 7 | * 8 | * 1. The shared file or redistribution must retain the information set out 9 | * above and this list of conditions. 10 | * 2. Derivative's name (Derivative Inc.) or its trademarks may not be used 11 | * to endorse or promote products derived from this file without specific 12 | * prior written permission from Derivative. 13 | */ 14 | 15 | #include "TOP_CPlusPlusBase.h" 16 | #include "cuda_runtime.h" 17 | #include 18 | #include 19 | #include 20 | 21 | using namespace TD; 22 | 23 | class ONNXCandyStyleTOP : public TOP_CPlusPlusBase 24 | { 25 | public: 26 | ONNXCandyStyleTOP(const OP_NodeInfo *info, TOP_Context *context); 27 | virtual ~ONNXCandyStyleTOP(); 28 | 29 | virtual void getGeneralInfo(TOP_GeneralInfo*, const OP_Inputs*, void* reserved1) override; 30 | //virtual bool getOutputFormat(TOP_OutputFormat*, const OP_Inputs*, void* reserved) override; 31 | 32 | 33 | virtual void execute(TOP_Output*, const OP_Inputs*, void* reserved) override; 34 | 35 | virtual int32_t getNumInfoCHOPChans(void* reserved) override; 36 | virtual void getInfoCHOPChan(int32_t index, 37 | OP_InfoCHOPChan *chan, 38 | void* reserved) override; 39 | 40 | virtual bool getInfoDATSize(OP_InfoDATSize *infoSize, void* reserved) override; 41 | virtual void getInfoDATEntries(int32_t index, 42 | int32_t nEntries, 43 | OP_InfoDATEntries *entries, 44 | void* reserved) override; 45 | 46 | virtual void getErrorString(OP_String *error, void* reserved) override; 47 | 48 | virtual void setupParameters(OP_ParameterManager *manager, void* reserved) override; 49 | virtual void pulsePressed(const char *name, void* reserved) override; 50 | 51 | private: 52 | bool checkORTStatus(OrtStatus* status, std::string* err); 53 | bool allocCUDAAndValue(void** cudaMemory, OrtValue** value, size_t size, const std::array& shape); 54 | 55 | // We don't need to store this pointer, but we do for the example. 56 | // The OP_NodeInfo class store information about the node that's using 57 | // this instance of the class (like its name). 58 | const OP_NodeInfo* myNodeInfo; 59 | 60 | cudaSurfaceObject_t myInputSurface = 0; 61 | cudaSurfaceObject_t myOutputSurface = 0; 62 | cudaStream_t myStream = 0; 63 | 64 | TOP_Context* myContext = nullptr; 65 | std::string myError; 66 | const OrtApi* myORT = nullptr; 67 | OrtEnv* myEnv = nullptr; 68 | OrtSessionOptions* mySessionOptions = nullptr; 69 | OrtSession* mySession = nullptr; 70 | OrtRunOptions* myRunOptions = nullptr; 71 | void* mySourceData = nullptr; 72 | OrtValue* mySourceTensor = nullptr; 73 | void* myDestData = nullptr; 74 | OrtValue* myDestTensor = nullptr; 75 | size_t myInputCount = 0; 76 | size_t myOutputCount = 0; 77 | 78 | }; 79 | -------------------------------------------------------------------------------- /TOP/ONNXCandyStyleTOP/ONNXCandyStyleTOP.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio Version 16 4 | VisualStudioVersion = 16.0.30503.244 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ONNXCandyStyleTOP", "ONNXCandyStyleTOP.vcxproj", "{C592EBF8-35BC-4214-8071-234B96CC6E46}" 7 | EndProject 8 | Global 9 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 10 | Debug|x64 = Debug|x64 11 | Release|x64 = Release|x64 12 | EndGlobalSection 13 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 14 | {C592EBF8-35BC-4214-8071-234B96CC6E46}.Debug|x64.ActiveCfg = Debug|x64 15 | {C592EBF8-35BC-4214-8071-234B96CC6E46}.Debug|x64.Build.0 = Debug|x64 16 | {C592EBF8-35BC-4214-8071-234B96CC6E46}.Release|x64.ActiveCfg = Release|x64 17 | {C592EBF8-35BC-4214-8071-234B96CC6E46}.Release|x64.Build.0 = Release|x64 18 | EndGlobalSection 19 | GlobalSection(SolutionProperties) = preSolution 20 | HideSolutionNode = FALSE 21 | EndGlobalSection 22 | GlobalSection(ExtensibilityGlobals) = postSolution 23 | SolutionGuid = {4C3DDFE4-7A57-483E-A9A1-26A7F0C58FBB} 24 | EndGlobalSection 25 | EndGlobal 26 | -------------------------------------------------------------------------------- /TOP/ONNXCandyStyleTOP/README.md: -------------------------------------------------------------------------------- 1 | # ONNX Candy Style TOP 2 | This example implements loading an ONNX based AI model using the [ONNX Runtime](https://onnxruntime.ai). It uses CUDA to execute the model. 3 | 4 | ## Prerequisites 5 | * Requires TouchDesigner 2023.12308, due to the onnx-runtime.dll version bundled with the installer. 6 | * 2023.12308 is available [here](https://www.dropbox.com/scl/fi/zl5vdxi9eufdiocv2592v/TouchDesigner.2023.12308.exe?rlkey=92hvqbytiyybc9lye2xnfh2g4&dl=0). 7 | * We hope to find a more general solution to this issue in the near future. 8 | * Requires an Nvidia GPU. Currently this example uses CUDA as the execution engine. 9 | * Requires the CUDA 11.8 Toolkit to be installed. 10 | * It requires ONNX runtime version 1.18.1, for CUDA 11. Newer ONNX runtime releases are only for CUDA 12. 11 | * The project currently looks for the headers/libs for ONNX in C:/Program Files/onnxruntime 12 | * Download 1.18.1 runtime from the [ONNX Github](https://github.com/microsoft/onnxruntime/releases/download/v1.18.1/onnxruntime-win-x64-gpu-1.18.1.zip). Unzip this into C:/Program Files/onnxruntime so the directories exist with the .lib and .h files: 13 | * C:/Program Files/onnxruntime/lib 14 | * C:/Program Files/onnxruntime/include 15 | * The .dll files from this are not used. The .dlls that come with TouchDesigner will be what is loaded. 16 | * It requires the __candy.onnx__ model, which is available on the [ONNX Examples Github](https://github.com/microsoft/onnxruntime-inference-examples/tree/main/c_cxx/fns_candy_style_transfer). The model is directly available [here](https://raw.githubusercontent.com/microsoft/Windows-Machine-Learning/master/Samples/FNSCandyStyleTransfer/UWP/cs/Assets/candy.onnx). 17 | * Place __candy.onxx__ next to the .dll generated by this project that you load into the CPlsuPlus TOP (or your Plugins directory where you place the .dll). 18 | 19 | This TOP takes one input which must be 8 bit RGBA, 720x270 resolution. 20 | -------------------------------------------------------------------------------- /TOP/ONNXCandyStyleTOP/kernel.cu: -------------------------------------------------------------------------------- 1 | /* Shared Use License: This file is owned by Derivative Inc. (Derivative) 2 | * and can only be used, and/or modified for use, in conjunction with 3 | * Derivative's TouchDesigner software, and only if you are a licensee who has 4 | * accepted Derivative's TouchDesigner license or assignment agreement 5 | * (which also govern the use of this file). You may share or redistribute 6 | * a modified version of this file provided the following conditions are met: 7 | * 8 | * 1. The shared file or redistribution must retain the information set out 9 | * above and this list of conditions. 10 | * 2. Derivative's name (Derivative Inc.) or its trademarks may not be used 11 | * to endorse or promote products derived from this file without specific 12 | * prior written permission from Derivative. 13 | */ 14 | 15 | #include "CPlusPlus_Common.h" 16 | #include "cuda_runtime.h" 17 | #include "device_launch_parameters.h" 18 | 19 | #include 20 | #include 21 | 22 | __global__ void 23 | copyRGBATToRGBPlanar(int width, int height, cudaSurfaceObject_t input, int64_t planeStride, float* output) 24 | { 25 | unsigned int x = blockIdx.x * blockDim.x + threadIdx.x; 26 | unsigned int y = blockIdx.y * blockDim.y + threadIdx.y; 27 | 28 | if (x >= width || y >= height) 29 | return; 30 | 31 | uchar4 color; 32 | surf2Dread(&color, input, x * 4, y, cudaBoundaryModeZero); 33 | int64_t pixelIndex = y * width + x; 34 | output[pixelIndex] = (float)color.x; 35 | output[pixelIndex + planeStride] = (float)color.y; 36 | output[pixelIndex + planeStride * 2] = (float)color.z; 37 | } 38 | 39 | __device__ unsigned char 40 | clampFloat(float v) 41 | { 42 | if (v < 0.0) 43 | return 0; 44 | if (v > 255.0) 45 | return 255; 46 | else 47 | return (unsigned char)v; 48 | } 49 | 50 | 51 | __global__ void 52 | copyRGBPlanarToRGBA(int width, int height, float* input, int64_t planeStride, cudaSurfaceObject_t output) 53 | { 54 | unsigned int x = blockIdx.x * blockDim.x + threadIdx.x; 55 | unsigned int y = blockIdx.y * blockDim.y + threadIdx.y; 56 | 57 | if (x >= width || y >= height) 58 | return; 59 | 60 | uchar4 color; 61 | int64_t pixelIndex = y * width + x; 62 | color.x = clampFloat(input[pixelIndex]); 63 | color.y = clampFloat(input[pixelIndex + planeStride]); 64 | color.z = clampFloat(input[pixelIndex + planeStride * 2]); 65 | color.w = 255; 66 | surf2Dwrite(color, output, x * 4, y, cudaBoundaryModeZero); 67 | } 68 | 69 | int 70 | divUp(int a, int b) 71 | { 72 | return ((a % b) != 0) ? (a / b + 1) : (a / b); 73 | } 74 | 75 | cudaError_t 76 | doCopyRGBATToRGBPlanar(int width, int height, int depth, TD::OP_TexDim dim, cudaSurfaceObject_t input, float* output, cudaStream_t stream) 77 | { 78 | cudaError_t cudaStatus; 79 | 80 | dim3 blockSize(16, 16, 1); 81 | dim3 gridSize(divUp(width, blockSize.x), divUp(height, blockSize.y), depth); 82 | 83 | copyRGBATToRGBPlanar << > > (width, height, input, width * height, output); 84 | 85 | #ifdef _DEBUG 86 | // any errors encountered during the launch. 87 | cudaStatus = cudaDeviceSynchronize(); 88 | if (cudaStatus != cudaSuccess) 89 | { 90 | fprintf(stderr, "cudaDeviceSynchronize returned error code %d after launching kernel!\n", cudaStatus); 91 | } 92 | #else 93 | cudaStatus = cudaSuccess; 94 | #endif 95 | 96 | return cudaStatus; 97 | } 98 | 99 | cudaError_t 100 | doCopyRGBPlanarToRGBA(int width, int height, int depth, TD::OP_TexDim dim, float* input, cudaSurfaceObject_t output, cudaStream_t stream) 101 | { 102 | cudaError_t cudaStatus; 103 | 104 | dim3 blockSize(16, 16, 1); 105 | dim3 gridSize(divUp(width, blockSize.x), divUp(height, blockSize.y), depth); 106 | 107 | copyRGBPlanarToRGBA << > > (width, height, input, width * height, output); 108 | 109 | #ifdef _DEBUG 110 | // any errors encountered during the launch. 111 | cudaStatus = cudaDeviceSynchronize(); 112 | if (cudaStatus != cudaSuccess) 113 | { 114 | fprintf(stderr, "cudaDeviceSynchronize returned error code %d after launching kernel!\n", cudaStatus); 115 | } 116 | #else 117 | cudaStatus = cudaSuccess; 118 | #endif 119 | 120 | return cudaStatus; 121 | } 122 | -------------------------------------------------------------------------------- /TOP/ObjectDetectorTOP/ObjectDetectorTOP.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio Version 16 4 | VisualStudioVersion = 16.0.30011.22 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ObjectDetectorTOP", "ObjectDetectorTOP.vcxproj", "{3F5BEECD-FA36-459F-91B8-BB481A67EF44}" 7 | EndProject 8 | Global 9 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 10 | Debug|x64 = Debug|x64 11 | Release|x64 = Release|x64 12 | EndGlobalSection 13 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 14 | {3F5BEECD-FA36-459F-91B8-BB481A67EF44}.Debug|x64.ActiveCfg = Debug|x64 15 | {3F5BEECD-FA36-459F-91B8-BB481A67EF44}.Debug|x64.Build.0 = Debug|x64 16 | {3F5BEECD-FA36-459F-91B8-BB481A67EF44}.Release|x64.ActiveCfg = Release|x64 17 | {3F5BEECD-FA36-459F-91B8-BB481A67EF44}.Release|x64.Build.0 = Release|x64 18 | EndGlobalSection 19 | GlobalSection(SolutionProperties) = preSolution 20 | HideSolutionNode = FALSE 21 | EndGlobalSection 22 | GlobalSection(ExtensibilityGlobals) = postSolution 23 | SolutionGuid = {CDCA304D-7173-47CC-BC43-257E4444266C} 24 | EndGlobalSection 25 | EndGlobal 26 | -------------------------------------------------------------------------------- /TOP/ObjectDetectorTOP/Parameters.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | class TD::OP_Inputs; 6 | class TD::OP_ParameterManager; 7 | 8 | #pragma region ParNames and ParLabels 9 | 10 | // Names of the parameters 11 | 12 | constexpr static char ClassifierName[] = "Classifier"; 13 | constexpr static char ClassifierLabel[] = "Classifier"; 14 | 15 | constexpr static char ScalefactorName[] = "Scalefactor"; 16 | constexpr static char ScalefactorLabel[] = "Scale Factor"; 17 | 18 | constexpr static char MinneighborsName[] = "Minneighbors"; 19 | constexpr static char MinneighborsLabel[] = "Min Neighbors"; 20 | 21 | constexpr static char LimitobjectsizeName[] = "Limitobjectsize"; 22 | constexpr static char LimitobjectsizeLabel[] = "Limit Object Size"; 23 | 24 | constexpr static char MinobjectwidthName[] = "Minobjectwidth"; 25 | constexpr static char MinobjectwidthLabel[] = "Min Object Width"; 26 | 27 | constexpr static char MinobjectheightName[] = "Minobjectheight"; 28 | constexpr static char MinobjectheightLabel[] = "Min Object Height"; 29 | 30 | constexpr static char MaxobjectwidthName[] = "Maxobjectwidth"; 31 | constexpr static char MaxobjectwidthLabel[] = "Max Object Width"; 32 | 33 | constexpr static char MaxobjectheightName[] = "Maxobjectheight"; 34 | constexpr static char MaxobjectheightLabel[] = "Max Object Height"; 35 | 36 | constexpr static char DrawboundingboxName[] = "Drawboundingbox"; 37 | constexpr static char DrawboundingboxLabel[] = "Draw Bounding Box"; 38 | 39 | constexpr static char LimitobjectsdetectedName[] = "Limitobjectsdetected"; 40 | constexpr static char LimitobjectsdetectedLabel[] = "Limit Objects Detected"; 41 | 42 | constexpr static char MaximumobjectsName[] = "Maximumobjects"; 43 | constexpr static char MaximumobjectsLabel[] = "Maximum Objects"; 44 | 45 | 46 | #pragma endregion 47 | 48 | #pragma region Menus 49 | #pragma endregion 50 | 51 | 52 | #pragma region Parameters 53 | class Parameters 54 | { 55 | public: 56 | static void setup(TD::OP_ParameterManager*); 57 | 58 | // Classifier 59 | static std::string evalClassifier(const TD::OP_Inputs* inputs); 60 | 61 | // Scale Factor 62 | static double evalScalefactor(const TD::OP_Inputs* inputs); 63 | 64 | // Min Neighbors 65 | static int evalMinneighbors(const TD::OP_Inputs* inputs); 66 | 67 | // Limit Object Size 68 | static bool evalLimitobjectsize(const TD::OP_Inputs* inputs); 69 | 70 | // Min Object Width 71 | static double evalMinobjectwidth(const TD::OP_Inputs* inputs); 72 | 73 | // Min Object Height 74 | static double evalMinobjectheight(const TD::OP_Inputs* inputs); 75 | 76 | // Max Object Width 77 | static double evalMaxobjectwidth(const TD::OP_Inputs* inputs); 78 | 79 | // Max Object Height 80 | static double evalMaxobjectheight(const TD::OP_Inputs* inputs); 81 | 82 | // Draw Bounding Box 83 | static bool evalDrawboundingbox(const TD::OP_Inputs* inputs); 84 | 85 | // Limit Objects Detected 86 | static bool evalLimitobjectsdetected(const TD::OP_Inputs* inputs); 87 | 88 | // Maximum Objects 89 | static int evalMaximumobjects(const TD::OP_Inputs* inputs); 90 | 91 | 92 | }; 93 | #pragma endregion -------------------------------------------------------------------------------- /TOP/ObjectDetectorTOP/README.md: -------------------------------------------------------------------------------- 1 | # Object Detector TOP 2 | 3 | This example implements a TOP to detect objects using OpenCV's Cascade Classifier. For 4 | more information on the parameters check cv::CascadeClassifier documentation. 5 | 6 | ## Prerequisites 7 | Requires a [reference](https://github.com/TouchDesigner/CustomOperatorSamples#referencing-opencv-libraries) to the OpenCV include and library folder. 8 | 9 | ## Parameters 10 | * **Classifier**: A path to a .xml pretrained classifier. It can be either Haar or 11 | LBP. OpenCV includes pretrained classiffiers and can be found in 12 | opencv/sources/data. 13 | * **Scale Factor**: Specifies how much the image size is reduced at each image scale. 14 | * **Min Neighbors**: How many neighbors each candidate rectangle should have to retain it. 15 | * **Limit Object Size**: If on, limit the size of the detected objects. 16 | * **Min Object Size**: Minimum possible object size. Objects smaller than that are ignored. 17 | * **Max Object Size**: Maximum possible object size. Objects larger than that are ignored. If 18 | maxSize == minSize model is evaluated on single scale. 19 | * **Draw Bounding Box**: If on, draw the bounding box of the detected object. 20 | * **Limit Objects Detected**: If on, limit the number of objects detected. Turn this parameter on 21 | if you need the channels outputted to CHOPInfo to be constant. 22 | * **Maximum Objects**: The maximum number of objects that the TOP can detects 23 | 24 | This TOP takes one input where to detect faces. Outputs the input data with the bounding boxes for the 25 | detected objects. 26 | 27 | ## Info CHOP and Info DAT outputs: 28 | * **objects_tracked**: Number of objects that we are currently tracking. 29 | * **obj#:tracked**: Whether this channel group is tracking an object. 30 | * **obj#:levelweight**: The certainty of classification at the final stage. This value can then be used 31 | to separate strong from weaker classifications. 32 | * **obj#:tx**: X position of the bounding box. 33 | * **obj#:ty**: Y position of the bounding box. 34 | * **obj#:w**: Width of the bounding box. 35 | * **obj#:h**: Height of the bounding box. 36 | -------------------------------------------------------------------------------- /TOP/OpticalFlowCPUTOP/OpticalFlowCPUTOP.h: -------------------------------------------------------------------------------- 1 | /* Shared Use License: This file is owned by Derivative Inc. (Derivative) 2 | * and can only be used, and/or modified for use, in conjunction with 3 | * Derivative's TouchDesigner software, and only if you are a licensee who has 4 | * accepted Derivative's TouchDesigner license or assignment agreement 5 | * (which also govern the use of this file). You may share or redistribute 6 | * a modified version of this file provided the following conditions are met: 7 | * 8 | * 1. The shared file or redistribution must retain the information set out 9 | * above and this list of conditions. 10 | * 2. Derivative's name (Derivative Inc.) or its trademarks may not be used 11 | * to endorse or promote products derived from this file without specific 12 | * prior written permission from Derivative. 13 | */ 14 | #ifndef __OpticalFlowCPUTOP__ 15 | #define __OpticalFlowCPUTOP__ 16 | 17 | #include "TOP_CPlusPlusBase.h" 18 | #include "Parameters.h" 19 | 20 | namespace cv 21 | { 22 | class Mat; 23 | } 24 | 25 | /* 26 | This example implements a TOP to expose cv::cuda::FarnebackOpticalFlow class functionallity. For 27 | more information on the parameters check 28 | https://docs.opencv.org/3.4/d9/d30/classcv_1_1cuda_1_1FarnebackOpticalFlow.html 29 | 30 | It takes the following parameters: 31 | - Num Levels: Number of pyramid layers including the intial image. 32 | - Pyramid Scale: Image scale to build pyramid layers. 33 | - Window Size: Averaging window size. 34 | - Iterations: Number of iteration at each pyramid level. 35 | - Poly N: Size of the pixel neighborhood used to find polynomial expansion in each pixel. 36 | - Poly Sigma: Standard deviation of the Gaussian thta is used to smooth derivatives used as 37 | basis for the polynomial expansion. 38 | - Use Gaussian Filter: Uses the Gaussian Window Size x Window Size filter instead of a box filter. 39 | - Use Previous Flow: Use the optical flow of the previous frame as an estimate for the current frame. 40 | 41 | This TOP takes one input where the optical flow of sequencial frames is calculated. 42 | */ 43 | 44 | // To get more help about these functions, look at TOP_CPlusPlusBase.h 45 | class OpticalFlowCPUTOP : public TD::TOP_CPlusPlusBase 46 | { 47 | public: 48 | OpticalFlowCPUTOP(const TD::OP_NodeInfo *info, TD::TOP_Context *context); 49 | virtual ~OpticalFlowCPUTOP(); 50 | 51 | virtual void getGeneralInfo(TD::TOP_GeneralInfo*, const TD::OP_Inputs*, void* reserved) override; 52 | 53 | virtual void execute(TD::TOP_Output*, const TD::OP_Inputs*, void* reserved) override; 54 | 55 | virtual void setupParameters(TD::OP_ParameterManager*, void* reserved) override; 56 | 57 | private: 58 | void inputToMat(const TD::OP_Inputs*); 59 | 60 | void cvMatToOutput(const cv::Mat&, TD::TOP_Output*, TD::TOP_UploadInfo) const; 61 | 62 | cv::Mat* myFrame; 63 | cv::Mat* myPrev; 64 | cv::Mat* myFlow; 65 | 66 | int myExecuteCount; 67 | TD::TOP_Context* myContext; 68 | TD::OP_SmartRef myPrevDownRes; 69 | 70 | Parameters myParms; 71 | }; 72 | 73 | #endif 74 | -------------------------------------------------------------------------------- /TOP/OpticalFlowCPUTOP/OpticalFlowCPUTOP.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio Version 16 4 | VisualStudioVersion = 16.0.30011.22 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "OpticalFlowCPUTOP", "OpticalFlowCPUTOP.vcxproj", "{3F5BEECD-FA36-459F-91B8-BB481A67EF44}" 7 | EndProject 8 | Global 9 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 10 | Debug|x64 = Debug|x64 11 | Release|x64 = Release|x64 12 | EndGlobalSection 13 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 14 | {3F5BEECD-FA36-459F-91B8-BB481A67EF44}.Debug|x64.ActiveCfg = Debug|x64 15 | {3F5BEECD-FA36-459F-91B8-BB481A67EF44}.Debug|x64.Build.0 = Debug|x64 16 | {3F5BEECD-FA36-459F-91B8-BB481A67EF44}.Release|x64.ActiveCfg = Release|x64 17 | {3F5BEECD-FA36-459F-91B8-BB481A67EF44}.Release|x64.Build.0 = Release|x64 18 | EndGlobalSection 19 | GlobalSection(SolutionProperties) = preSolution 20 | HideSolutionNode = FALSE 21 | EndGlobalSection 22 | GlobalSection(ExtensibilityGlobals) = postSolution 23 | SolutionGuid = {CDCA304D-7173-47CC-BC43-257E4444266C} 24 | EndGlobalSection 25 | EndGlobal 26 | -------------------------------------------------------------------------------- /TOP/OpticalFlowCPUTOP/Parameters.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | class TD::OP_Inputs; 6 | class TD::OP_ParameterManager; 7 | 8 | #pragma region ParNames and ParLabels 9 | 10 | // Names of the parameters 11 | 12 | constexpr static char NumlevelsName[] = "Numlevels"; 13 | constexpr static char NumlevelsLabel[] = "Num Levels"; 14 | 15 | constexpr static char PyramidscaleName[] = "Pyramidscale"; 16 | constexpr static char PyramidscaleLabel[] = "Pyramid Scale"; 17 | 18 | constexpr static char WindowsizeName[] = "Windowsize"; 19 | constexpr static char WindowsizeLabel[] = "Window Size"; 20 | 21 | constexpr static char IterationsName[] = "Iterations"; 22 | constexpr static char IterationsLabel[] = "Iterations"; 23 | 24 | constexpr static char PolynName[] = "Polyn"; 25 | constexpr static char PolynLabel[] = "Poly N"; 26 | 27 | constexpr static char PolysigmaName[] = "Polysigma"; 28 | constexpr static char PolysigmaLabel[] = "Poly Sigma"; 29 | 30 | constexpr static char UsegaussianfilterName[] = "Usegaussianfilter"; 31 | constexpr static char UsegaussianfilterLabel[] = "Use Gaussian Filter"; 32 | 33 | constexpr static char UsepreviousflowName[] = "Usepreviousflow"; 34 | constexpr static char UsepreviousflowLabel[] = "Use Previous Flow"; 35 | 36 | constexpr static char ChannelName[] = "Channel"; 37 | constexpr static char ChannelLabel[] = "Channel"; 38 | 39 | 40 | #pragma endregion 41 | 42 | #pragma region Menus 43 | enum class ChannelMenuItems 44 | { 45 | R, 46 | G, 47 | B, 48 | A 49 | }; 50 | 51 | #pragma endregion 52 | 53 | 54 | #pragma region Parameters 55 | class Parameters 56 | { 57 | public: 58 | static void setup(TD::OP_ParameterManager*); 59 | 60 | // Num Levels 61 | static int evalNumlevels(const TD::OP_Inputs* inputs); 62 | 63 | // Pyramid Scale 64 | static double evalPyramidscale(const TD::OP_Inputs* inputs); 65 | 66 | // Window Size 67 | static int evalWindowsize(const TD::OP_Inputs* inputs); 68 | 69 | // Iterations 70 | static int evalIterations(const TD::OP_Inputs* inputs); 71 | 72 | // Poly N 73 | static int evalPolyn(const TD::OP_Inputs* inputs); 74 | 75 | // Poly Sigma 76 | static double evalPolysigma(const TD::OP_Inputs* inputs); 77 | 78 | // Use Gaussian Filter 79 | static bool evalUsegaussianfilter(const TD::OP_Inputs* inputs); 80 | 81 | // Use Previous Flow 82 | static bool evalUsepreviousflow(const TD::OP_Inputs* inputs); 83 | 84 | // Channel 85 | static ChannelMenuItems evalChannel(const TD::OP_Inputs* inputs); 86 | 87 | 88 | }; 89 | #pragma endregion -------------------------------------------------------------------------------- /TOP/OpticalFlowCPUTOP/README.md: -------------------------------------------------------------------------------- 1 | # Optical Flow (CPU) TOP 2 | 3 | This example implements a TOP to expose cv::cuda::FarnebackOpticalFlow class functionallity. 4 | 5 | For more information on the parameters check 6 | https://docs.opencv.org/3.4/d9/d30/classcv_1_1cuda_1_1FarnebackOpticalFlow.html 7 | 8 | ## Prerequisites 9 | Requires a [reference](https://github.com/TouchDesigner/CustomOperatorSamples#referencing-opencv-libraries) to the OpenCV include and library folder. 10 | 11 | ## Parameters 12 | * **Num Levels**: Number of pyramid layers including the intial image. 13 | * **Pyramid Scale**: Image scale to build pyramid layers. 14 | * **Window Size**: Averaging window size. 15 | * **Iterations**: Number of iteration at each pyramid level. 16 | * **Poly N**: Size of the pixel neighborhood used to find polynomial expansion in each pixel. 17 | * **Poly Sigma**: Standard deviation of the Gaussian thta is used to smooth derivatives used as 18 | basis for the polynomial expansion. 19 | * **Use Gaussian Filter**: Uses the Gaussian Window Size x Window Size filter instead of a box filter. 20 | * **Use Previous Flow**: Use the optical flow of the previous frame as an estimate for the current frame. 21 | 22 | This TOP takes one input where the optical flow of sequential frames is calculated. 23 | -------------------------------------------------------------------------------- /TOP/SpectrumTOP/GpuUtils.cuh: -------------------------------------------------------------------------------- 1 | #ifndef __GPUUTILS__ 2 | #define __GPUUTILS__ 3 | 4 | struct cudaArray; 5 | namespace cv 6 | { 7 | namespace cuda 8 | { 9 | class GpuMat; 10 | } 11 | } 12 | 13 | namespace GpuUtils 14 | { 15 | enum class ChannelFormat 16 | { 17 | U8, 18 | U16, 19 | F16, 20 | F32, 21 | F11, 22 | RGB102A 23 | }; 24 | 25 | void arrayToComplexMatGPU(int width, int height, cudaArray* input, cv::cuda::GpuMat& output, int numChannels, int channel, ChannelFormat cf); 26 | 27 | void complexMatGPUToArray(int width, int height, const cv::cuda::GpuMat& input, cudaArray* output); 28 | 29 | void matGPUToArray(int width, int height, const cv::cuda::GpuMat& input, cudaArray* output, int pixelSize); 30 | 31 | void arrayToMatGPU(int width, int height, cudaArray* input, cv::cuda::GpuMat& output, int pixelSize); 32 | } 33 | #endif 34 | -------------------------------------------------------------------------------- /TOP/SpectrumTOP/Parameters.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include "CPlusPlus_Common.h" 4 | #include "Parameters.h" 5 | 6 | #pragma region Evals 7 | 8 | ModeMenuItems 9 | Parameters::evalMode(const TD::OP_Inputs* inputs) 10 | { 11 | return static_cast(inputs->getParInt(ModeName)); 12 | } 13 | 14 | CoordMenuItems 15 | Parameters::evalCoord(const TD::OP_Inputs* inputs) 16 | { 17 | return static_cast(inputs->getParInt(CoordName)); 18 | } 19 | 20 | ChanMenuItems 21 | Parameters::evalChan(const TD::OP_Inputs* inputs) 22 | { 23 | return static_cast(inputs->getParInt(ChanName)); 24 | } 25 | 26 | bool 27 | Parameters::evalTransrows(const TD::OP_Inputs* inputs) 28 | { 29 | return inputs->getParInt(TransrowsName) ? true : false; 30 | } 31 | 32 | 33 | #pragma endregion 34 | 35 | #pragma region Setup 36 | 37 | void 38 | Parameters::setup(TD::OP_ParameterManager* manager) 39 | { 40 | { 41 | TD::OP_StringParameter p; 42 | p.name = ModeName; 43 | p.label = ModeLabel; 44 | p.page = "Spectrum"; 45 | p.defaultValue = "dft"; 46 | std::array Names = 47 | { 48 | "dft", 49 | "idft" 50 | }; 51 | std::array Labels = 52 | { 53 | "Discrete Fourier Transform", 54 | "Inverse Discrete Fourier Transform" 55 | }; 56 | TD::OP_ParAppendResult res = manager->appendMenu(p, Names.size(), Names.data(), Labels.data()); 57 | 58 | assert(res == TD::OP_ParAppendResult::Success); 59 | } 60 | 61 | { 62 | TD::OP_StringParameter p; 63 | p.name = CoordName; 64 | p.label = CoordLabel; 65 | p.page = "Spectrum"; 66 | p.defaultValue = "polar"; 67 | std::array Names = 68 | { 69 | "polar", 70 | "cartesian" 71 | }; 72 | std::array Labels = 73 | { 74 | "Polar (Magnitude, Phase)", 75 | "Cartesian (Real, Imaginary)" 76 | }; 77 | TD::OP_ParAppendResult res = manager->appendMenu(p, Names.size(), Names.data(), Labels.data()); 78 | 79 | assert(res == TD::OP_ParAppendResult::Success); 80 | } 81 | 82 | { 83 | TD::OP_StringParameter p; 84 | p.name = ChanName; 85 | p.label = ChanLabel; 86 | p.page = "Spectrum"; 87 | p.defaultValue = "r"; 88 | std::array Names = 89 | { 90 | "r", 91 | "g", 92 | "b", 93 | "a" 94 | }; 95 | std::array Labels = 96 | { 97 | "R", 98 | "G", 99 | "B", 100 | "A" 101 | }; 102 | TD::OP_ParAppendResult res = manager->appendMenu(p, Names.size(), Names.data(), Labels.data()); 103 | 104 | assert(res == TD::OP_ParAppendResult::Success); 105 | } 106 | 107 | { 108 | TD::OP_NumericParameter p; 109 | p.name = TransrowsName; 110 | p.label = TransrowsLabel; 111 | p.page = "Spectrum"; 112 | p.defaultValues[0] = false; 113 | 114 | TD::OP_ParAppendResult res = manager->appendToggle(p); 115 | 116 | assert(res == TD::OP_ParAppendResult::Success); 117 | } 118 | 119 | 120 | } 121 | 122 | #pragma endregion -------------------------------------------------------------------------------- /TOP/SpectrumTOP/Parameters.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | class TD::OP_Inputs; 6 | class TD::OP_ParameterManager; 7 | 8 | #pragma region ParNames and ParLabels 9 | 10 | // Names of the parameters 11 | 12 | constexpr static char ModeName[] = "Mode"; 13 | constexpr static char ModeLabel[] = "Mode"; 14 | 15 | constexpr static char CoordName[] = "Coord"; 16 | constexpr static char CoordLabel[] = "Coordinate System"; 17 | 18 | constexpr static char ChanName[] = "Chan"; 19 | constexpr static char ChanLabel[] = "Channel"; 20 | 21 | constexpr static char TransrowsName[] = "Transrows"; 22 | constexpr static char TransrowsLabel[] = "Transform Rows"; 23 | 24 | 25 | #pragma endregion 26 | 27 | #pragma region Menus 28 | enum class ModeMenuItems 29 | { 30 | dft, 31 | idft 32 | }; 33 | 34 | enum class CoordMenuItems 35 | { 36 | polar, 37 | cartesian 38 | }; 39 | 40 | enum class ChanMenuItems 41 | { 42 | r, 43 | g, 44 | b, 45 | a 46 | }; 47 | 48 | #pragma endregion 49 | 50 | 51 | #pragma region Parameters 52 | class Parameters 53 | { 54 | public: 55 | static void setup(TD::OP_ParameterManager*); 56 | 57 | // Mode 58 | static ModeMenuItems evalMode(const TD::OP_Inputs* inputs); 59 | 60 | // Coordinate System 61 | static CoordMenuItems evalCoord(const TD::OP_Inputs* inputs); 62 | 63 | // Channel 64 | static ChanMenuItems evalChan(const TD::OP_Inputs* inputs); 65 | 66 | // Transform Rows 67 | static bool evalTransrows(const TD::OP_Inputs* inputs); 68 | 69 | 70 | }; 71 | #pragma endregion -------------------------------------------------------------------------------- /TOP/SpectrumTOP/README.md: -------------------------------------------------------------------------------- 1 | # Spectrum TOP 2 | 3 | This example implements a TOP to calculate the Fourier Transform of a TOP using OpenCV's cuda functionallity. 4 | 5 | For more information on image Fourier Transforms [read this OpenCV article](https://docs.opencv.org/4.x/de/dbc/tutorial_py_fourier_transform.html) 6 | 7 | 8 | 9 | ## Prerequisites 10 | Requires a [reference](https://github.com/TouchDesigner/CustomOperatorSamples#referencing-opencv-libraries) to the OpenCV include and library folder. 11 | 12 | Requires the CUDA Toolkit to be [installed](https://github.com/TouchDesigner/CustomOperatorSamples/blob/main/README.md#installing-the-cuda-toolkit). 13 | 14 | ## Parameters 15 | * **Transform**: One of [Image To DFT, DFT To Image], which determines if we calculate the forward or 16 | inverse fourier transform. 17 | * **Coordinate System**: One of [Polar, Cartesian]. If the transform is Image To DFT the output will be 18 | in the selected coordinate system. If the transform is DFT To Image the input must be in the 19 | coordinate system selected. 20 | * **Channel**: Active when Transform is Image To DFT. Selects which channel will be used to calculate the transform. 21 | * **Per Rows**: If On, it calculates the fourier transform of each row independently. 22 | 23 | This TOP takes one input. If the inverse is to be calculated the input must have 24 | exactly 2 32-bit float channels. 25 | -------------------------------------------------------------------------------- /TOP/SpectrumTOP/SpectrumTOP.h: -------------------------------------------------------------------------------- 1 | /* Shared Use License: This file is owned by Derivative Inc. (Derivative) 2 | * and can only be used, and/or modified for use, in conjunction with 3 | * Derivative's TouchDesigner software, and only if you are a licensee who has 4 | * accepted Derivative's TouchDesigner license or assignment agreement 5 | * (which also govern the use of this file). You may share or redistribute 6 | * a modified version of this file provided the following conditions are met: 7 | * 8 | * 1. The shared file or redistribution must retain the information set out 9 | * above and this list of conditions. 10 | * 2. Derivative's name (Derivative Inc.) or its trademarks may not be used 11 | * to endorse or promote products derived from this file without specific 12 | * prior written permission from Derivative. 13 | */ 14 | 15 | #ifndef __SpectrumTOP__ 16 | #define __SpectrumTOP__ 17 | 18 | #include "TOP_CPlusPlusBase.h" 19 | #include "Parameters.h" 20 | 21 | #include 22 | #include 23 | 24 | using namespace TD; 25 | 26 | namespace cv 27 | { 28 | namespace cuda 29 | { 30 | class GpuMat; 31 | } 32 | } 33 | 34 | namespace GpuUtils 35 | { 36 | enum class ChannelFormat; 37 | } 38 | 39 | /* 40 | This example implements a TOP to calculate the fourier transform using OpenCV's CUDA functionallity. 41 | 42 | It takes the following parameters: 43 | - Transform: One of [Image To DFT, DFT To Image], which determines if we calculate the forward or 44 | inverse fourier transform. 45 | - Coordinate System: One of [Polar, Cartesian]. If the transform is Image To DFT the output will be 46 | in the selected coordinate system. If the transform is DFT To Image the input must be in the 47 | coordinate system selected. 48 | - Channel: Active when Transform is Image To DFT. Selects which channel will be used to calculate the transform. 49 | - Per Rows: If On, it calculates the fourier transform of each row independently. 50 | 51 | This TOP takes one input. If the inverse is to be calculated the input must have 52 | exactly 2 32-bit float channels. 53 | */ 54 | 55 | // To get more help about these functions, look at TOP_CPlusPlusBase.h 56 | class SpectrumTOP : public TOP_CPlusPlusBase 57 | { 58 | public: 59 | SpectrumTOP(const OP_NodeInfo *info, TOP_Context *context); 60 | virtual ~SpectrumTOP(); 61 | 62 | virtual void getGeneralInfo(TOP_GeneralInfo*, const TD::OP_Inputs*, void* reserved) override; 63 | 64 | virtual void execute(TOP_Output*, const TD::OP_Inputs*, void* reserved) override; 65 | 66 | virtual void setupParameters(TD::OP_ParameterManager*, void* reserved) override; 67 | 68 | virtual void getErrorString(OP_String*, void* reserved) override; 69 | 70 | private: 71 | bool checkInputTop(const OP_TOPInput*, const TD::OP_Inputs*); 72 | 73 | void swapQuadrants(cv::cuda::GpuMat&); 74 | 75 | void swapSides(cv::cuda::GpuMat&); 76 | 77 | cv::cuda::GpuMat* myFrame; 78 | cv::cuda::GpuMat* myResult; 79 | 80 | std::string myError; 81 | 82 | // In this example this value will be incremented each time the execute() 83 | // function is called, then passes back to the TOP 84 | int32_t myExecuteCount; 85 | 86 | int myNumChan; 87 | GpuUtils::ChannelFormat myChanFormat; 88 | 89 | cv::Size mySize; 90 | 91 | TOP_Context* myContext; 92 | cudaStream_t myStream; 93 | Parameters myParms; 94 | }; 95 | 96 | #endif 97 | -------------------------------------------------------------------------------- /TOP/SpectrumTOP/SpectrumTOP.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio Version 16 4 | VisualStudioVersion = 16.0.30011.22 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "SpectrumTOP", "SpectrumTOP.vcxproj", "{3F5BEECD-FA36-459F-91B8-BB481A67EF44}" 7 | EndProject 8 | Global 9 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 10 | Debug|x64 = Debug|x64 11 | Release|x64 = Release|x64 12 | EndGlobalSection 13 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 14 | {3F5BEECD-FA36-459F-91B8-BB481A67EF44}.Debug|x64.ActiveCfg = Debug|x64 15 | {3F5BEECD-FA36-459F-91B8-BB481A67EF44}.Debug|x64.Build.0 = Debug|x64 16 | {3F5BEECD-FA36-459F-91B8-BB481A67EF44}.Release|x64.ActiveCfg = Release|x64 17 | {3F5BEECD-FA36-459F-91B8-BB481A67EF44}.Release|x64.Build.0 = Release|x64 18 | EndGlobalSection 19 | GlobalSection(SolutionProperties) = preSolution 20 | HideSolutionNode = FALSE 21 | EndGlobalSection 22 | GlobalSection(ExtensibilityGlobals) = postSolution 23 | SolutionGuid = {CDCA304D-7173-47CC-BC43-257E4444266C} 24 | EndGlobalSection 25 | EndGlobal 26 | -------------------------------------------------------------------------------- /images/image1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TouchDesigner/CustomOperatorSamples/ede7acf320a92b3e46df18e56af9b08867c22e10/images/image1.png -------------------------------------------------------------------------------- /images/image10.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TouchDesigner/CustomOperatorSamples/ede7acf320a92b3e46df18e56af9b08867c22e10/images/image10.png -------------------------------------------------------------------------------- /images/image2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TouchDesigner/CustomOperatorSamples/ede7acf320a92b3e46df18e56af9b08867c22e10/images/image2.png -------------------------------------------------------------------------------- /images/image3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TouchDesigner/CustomOperatorSamples/ede7acf320a92b3e46df18e56af9b08867c22e10/images/image3.png -------------------------------------------------------------------------------- /images/image4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TouchDesigner/CustomOperatorSamples/ede7acf320a92b3e46df18e56af9b08867c22e10/images/image4.png -------------------------------------------------------------------------------- /images/image5.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TouchDesigner/CustomOperatorSamples/ede7acf320a92b3e46df18e56af9b08867c22e10/images/image5.png -------------------------------------------------------------------------------- /images/image6.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TouchDesigner/CustomOperatorSamples/ede7acf320a92b3e46df18e56af9b08867c22e10/images/image6.png -------------------------------------------------------------------------------- /images/image7.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TouchDesigner/CustomOperatorSamples/ede7acf320a92b3e46df18e56af9b08867c22e10/images/image7.png -------------------------------------------------------------------------------- /images/image8.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TouchDesigner/CustomOperatorSamples/ede7acf320a92b3e46df18e56af9b08867c22e10/images/image8.png -------------------------------------------------------------------------------- /images/image9.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TouchDesigner/CustomOperatorSamples/ede7acf320a92b3e46df18e56af9b08867c22e10/images/image9.png --------------------------------------------------------------------------------