├── .gitignore ├── screenshot.png ├── src ├── touchdesigner │ ├── GL_Extensions.h │ ├── OpenCVCameraCalibrationDAT.hpp │ ├── OpenCVCameraCalibrationDAT.cpp │ ├── DAT_CPlusPlusBase.h │ └── CPlusPlus_Common.h ├── CMakeLists.txt ├── CameraCalibrator.hpp └── CameraCalibrator.cpp ├── example ├── CameraCalibrator.tox ├── CameraCalibration.toe ├── Images │ ├── Calibration.0.png │ ├── Calibration.1.png │ ├── Calibration.2.png │ ├── Calibration.3.png │ ├── Calibration.4.png │ ├── Calibration.5.png │ └── Calibration.6.png └── dll │ └── CameraCalibrationDAT.dll ├── calibration-pattern └── referenc.chessboard.png ├── README.md └── LICENSE /.gitignore: -------------------------------------------------------------------------------- 1 | # Build directory 2 | build/ 3 | 4 | # Example 5 | example/Backup/ 6 | **.*.toe -------------------------------------------------------------------------------- /screenshot.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/guidoschmidt/touchdesigner.camera-calibration/HEAD/screenshot.png -------------------------------------------------------------------------------- /src/touchdesigner/GL_Extensions.h: -------------------------------------------------------------------------------- 1 | // Stub file for simpler CHOP usage than an OpenGLTOP 2 | 3 | #include 4 | -------------------------------------------------------------------------------- /example/CameraCalibrator.tox: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/guidoschmidt/touchdesigner.camera-calibration/HEAD/example/CameraCalibrator.tox -------------------------------------------------------------------------------- /example/CameraCalibration.toe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/guidoschmidt/touchdesigner.camera-calibration/HEAD/example/CameraCalibration.toe -------------------------------------------------------------------------------- /example/Images/Calibration.0.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/guidoschmidt/touchdesigner.camera-calibration/HEAD/example/Images/Calibration.0.png -------------------------------------------------------------------------------- /example/Images/Calibration.1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/guidoschmidt/touchdesigner.camera-calibration/HEAD/example/Images/Calibration.1.png -------------------------------------------------------------------------------- /example/Images/Calibration.2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/guidoschmidt/touchdesigner.camera-calibration/HEAD/example/Images/Calibration.2.png -------------------------------------------------------------------------------- /example/Images/Calibration.3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/guidoschmidt/touchdesigner.camera-calibration/HEAD/example/Images/Calibration.3.png -------------------------------------------------------------------------------- /example/Images/Calibration.4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/guidoschmidt/touchdesigner.camera-calibration/HEAD/example/Images/Calibration.4.png -------------------------------------------------------------------------------- /example/Images/Calibration.5.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/guidoschmidt/touchdesigner.camera-calibration/HEAD/example/Images/Calibration.5.png -------------------------------------------------------------------------------- /example/Images/Calibration.6.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/guidoschmidt/touchdesigner.camera-calibration/HEAD/example/Images/Calibration.6.png -------------------------------------------------------------------------------- /example/dll/CameraCalibrationDAT.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/guidoschmidt/touchdesigner.camera-calibration/HEAD/example/dll/CameraCalibrationDAT.dll -------------------------------------------------------------------------------- /calibration-pattern/referenc.chessboard.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/guidoschmidt/touchdesigner.camera-calibration/HEAD/calibration-pattern/referenc.chessboard.png -------------------------------------------------------------------------------- /src/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | project(CameraCalibration) 2 | cmake_minimum_required(VERSION 2.6) 3 | 4 | set(CMAKE_CXX_STANDARD 11) 5 | 6 | find_package(OpenCV REQUIRED) 7 | include_directories(BEFORE ${OpenCV_INCLUDE_DIRS}) 8 | 9 | add_library(CameraCalibrationDAT 10 | SHARED 11 | ./CameraCalibrator.cpp 12 | ./touchdesigner/OpenCVCameraCalibrationDAT.cpp) 13 | target_include_directories(CameraCalibrationDAT 14 | PRIVATE 15 | . 16 | ./touchdesigner/) 17 | source_group("Header Files" 18 | FILES 19 | ./touchdesigner/CPlusPlus_Common.h 20 | ./touchdesigner/DAT_CPlusPlusBase.h 21 | ./touchdesigner/GL_Extensions.h 22 | ./tochdesigner/OpenCVCameraCalibrationDAT.hpp) 23 | target_link_libraries(CameraCalibrationDAT ${OpenCV_LIBS}) 24 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Touchdesigner Camera Calibration 2 | ### Touchdesigner C++ DAT for camera calibration with OpenCV 3 | 4 | ![Camera calibration screenshot](screenshot.png) 5 | 6 | ## Building 7 | - Get [CMake](https://cmake.org/) 8 | - Get [OpenCV](https://opencv.org/), extract it somewhere on your disk 9 | - Create a `build` directory 10 | - Point your CMake source directory to the `src` directory 11 | - In CMake set the `OpenCV_DIR` to `%YOUR_OPENCV_DIR%/opencv/build/x64/vc15/lib` 12 | - **Configure** + **Generate**, Open the solution file in Visual Studio and build 13 | the `CameraCalibrationDAT.dll` 14 | 15 | ## Why a DAT? 16 | TODO 17 | 18 | ## TODO 19 | - [ ] Component for capturing images of the calibration pattern 20 | - [ ] Fix asynchronous thread execution 21 | - [ ] Cache calibration parameters 22 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2020 Guido Schmidt 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /src/CameraCalibrator.hpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | class CameraCalibrator { 5 | private: 6 | // Checkerboard parameters 7 | int _imageCount; 8 | std::vector _images; 9 | std::vector _imageFiles; 10 | cv::Size _imageSize; 11 | cv::Size _boardSize; 12 | int _squareSizeInCm; 13 | bool _findCalibrationPatternFlags; 14 | bool _isCalibrated; 15 | 16 | // Measurements 17 | std::vector _inputImages; 18 | std::vector _pointsFromCheckerboardImages; 19 | std::vector> _measurementPointList; 20 | std::vector> _referencePointList; 21 | 22 | // Calibration parameters 23 | std::vector _rotationVectors; 24 | std::vector _translationVectors; 25 | std::vector _reprojectionErrors; 26 | cv::Mat _cameraMatrix; 27 | cv::Mat _distortionCoefficientMatrix; 28 | bool _performCalibrationFlags; 29 | cv::Vec2d _aperture; 30 | cv::Vec2d _fieldOfViewInDegrees; 31 | double _focalLength; 32 | cv::Point2d _principalPointInMilliMeter; 33 | double _aspectRatio; 34 | 35 | std::vector calculateChessboardReferencePoints(); 36 | 37 | public: 38 | CameraCalibrator(); 39 | ~CameraCalibrator(); 40 | 41 | // Algorithmic 42 | void addImageFile(std::string filePath); 43 | void evaluateImageStack(); 44 | void getCameraIntrinsics(); 45 | void performCalibration(); 46 | void clearImageFiles(); 47 | cv::Mat undistorImage(cv::Mat image); 48 | 49 | // Getter 50 | cv::Vec2d getAperture(); 51 | cv::Vec2d getFieldOfViewInDegrees(); 52 | double getFocalLength(); 53 | cv::Point2d getPrincipalPointInMillimeter(); 54 | double getAspectRatio(); 55 | cv::Mat getCameraMatrix(); 56 | std::vector getRotationVectors(); 57 | std::vector getTranslationVectors(); 58 | std::vector getReprojectionErrors(); 59 | cv::Mat getDistortionCoefficientMatrix(); 60 | std::vector getImageFiles(); 61 | inline bool isCalibrated() { return _isCalibrated; } 62 | }; 63 | -------------------------------------------------------------------------------- /src/touchdesigner/OpenCVCameraCalibrationDAT.hpp: -------------------------------------------------------------------------------- 1 | /* Shared Use License: This file is owned by Derivative Inc. (Derivative) and 2 | * 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 (which 5 | * also govern the use of this file). You may share a modified version of this 6 | * file with another authorized licensee of Derivative's TouchDesigner software. 7 | * Otherwise, no redistribution or sharing of this file, with or without 8 | * modification, is permitted. 9 | */ 10 | 11 | #include "DAT_CPlusPlusBase.h" 12 | #include "CameraCalibrator.hpp" 13 | #include 14 | 15 | /* 16 | This is a basic sample project to represent the usage of CPlusPlus DAT API. 17 | To get more help about these functions, look at DAT_CPlusPlusBase.h 18 | */ 19 | 20 | class CPlusPlusDATExample : public DAT_CPlusPlusBase 21 | { 22 | public: 23 | CPlusPlusDATExample(const OP_NodeInfo* info); 24 | virtual ~CPlusPlusDATExample(); 25 | 26 | virtual void getGeneralInfo(DAT_GeneralInfo*, const OP_Inputs*, void* reserved1) override; 27 | virtual void execute(DAT_Output*, const OP_Inputs*, void* reserved) override; 28 | virtual int32_t getNumInfoCHOPChans(void* reserved1) override; 29 | virtual void getInfoCHOPChan(int index, OP_InfoCHOPChan* chan, void* reserved1) override; 30 | virtual bool getInfoDATSize(OP_InfoDATSize* infoSize, void* reserved1) override; 31 | virtual void getInfoDATEntries(int32_t index, int32_t nEntries, OP_InfoDATEntries* entries, void* reserved1) override; 32 | 33 | virtual void setupParameters(OP_ParameterManager* manager, void* reserved1) override; 34 | virtual void pulsePressed(const char* name, void* reserved1) override; 35 | 36 | private: 37 | void makeTable(DAT_Output* output, int numRows, int numCols); 38 | void performCalibrationAsync(); 39 | 40 | // We don't need to store this pointer, but we do for the example. 41 | // The OP_NodeInfo class store information about the node that's using 42 | // this instance of the class (like its name). 43 | const OP_NodeInfo* myNodeInfo; 44 | 45 | // In this example this value will be incremented each time the execute() 46 | // function is called, then passes back to the DAT 47 | int32_t myExecuteCount; 48 | double myOffset; 49 | std::string myChopChanName; 50 | float myChopChanVal; 51 | std::string myChop; 52 | std::string myDat; 53 | CameraCalibrator* _cameraCalibrator; 54 | }; 55 | -------------------------------------------------------------------------------- /src/CameraCalibrator.cpp: -------------------------------------------------------------------------------- 1 | #include "CameraCalibrator.hpp" 2 | 3 | CameraCalibrator::CameraCalibrator() { 4 | _isCalibrated = false; 5 | // Checkerboard parameters 6 | this->_imageCount = 1; 7 | this->_images = {}; 8 | this->_imageFiles = {}; 9 | this->_imageSize = cv::Size(1920, 1080); 10 | this->_boardSize = cv::Size(9, 6); 11 | this->_squareSizeInCm = 5; 12 | this->_findCalibrationPatternFlags = 13 | cv::CALIB_CB_ADAPTIVE_THRESH | 14 | cv::CALIB_CB_FAST_CHECK | 15 | cv::CALIB_CB_NORMALIZE_IMAGE; 16 | 17 | // Measurements 18 | this->_inputImages = {}; 19 | this->_pointsFromCheckerboardImages = {}; 20 | this->_measurementPointList = {}; 21 | this->_referencePointList = {}; 22 | 23 | // Calibration parameters 24 | this->_rotationVectors = {}; 25 | this->_translationVectors = {}; 26 | this->_reprojectionErrors = {}; 27 | this->_cameraMatrix = cv::Mat::eye(3, 3, CV_64F); 28 | this->_distortionCoefficientMatrix = cv::Mat::zeros(8, 1, CV_64F); 29 | this->_performCalibrationFlags = 30 | // CV_CALIB_FIX_K1 | 31 | cv::CALIB_FIX_K4 | 32 | cv::CALIB_FIX_K5; 33 | // CV_CALIB_FIX_K6; 34 | // CV_CALIB_FIX_ASPECT_RATIO; 35 | 36 | // CV_CALIB_USE_INTRINSIC_GUESS 37 | // CV_CALIB_FIX_PRINCIPAL_POINT 38 | // CALIB_FIX_S1_S2_S3_S4 39 | } 40 | 41 | CameraCalibrator::~CameraCalibrator() {} 42 | 43 | void CameraCalibrator::addImageFile(std::string filePath) 44 | { 45 | this->_imageFiles.push_back(filePath); 46 | } 47 | 48 | void CameraCalibrator::clearImageFiles() { 49 | _imageFiles.clear(); 50 | } 51 | 52 | std::vector CameraCalibrator::getImageFiles() { 53 | return _imageFiles; 54 | } 55 | 56 | void CameraCalibrator::evaluateImageStack() 57 | { 58 | std::vector checkerboardPoints = {}; 59 | checkerboardPoints = this->calculateChessboardReferencePoints(); 60 | std::cout << "Evaluation: using " << this->_imageFiles.size() << " images." << std::endl; 61 | for (unsigned int i = 0; i < this->_imageFiles.size(); i++) { 62 | std::vector foundPointsBuffer = {}; 63 | /// Read input 64 | std::string filename = this->_imageFiles[i]; 65 | std::cout << "Evaluation: " << filename; 66 | cv::Mat image = cv::imread(filename); 67 | this->_images.push_back(image); 68 | /// Find chessboard 69 | cv::findChessboardCorners(image, 70 | this->_boardSize, 71 | foundPointsBuffer, 72 | this->_findCalibrationPatternFlags); 73 | cv::drawChessboardCorners(image, 74 | this->_boardSize, 75 | cv::Mat(foundPointsBuffer), 76 | true); 77 | std::cout << foundPointsBuffer.size() << std::endl; 78 | if (foundPointsBuffer.size() == 0) { continue; } 79 | this->_measurementPointList.push_back(foundPointsBuffer); 80 | this->_referencePointList.push_back(checkerboardPoints); 81 | this->_imageSize = cv::Size(image.rows, image.cols); 82 | } 83 | for (int i = 0; i < this->_measurementPointList.size(); ++i) { 84 | this->_referencePointList[i].resize(_measurementPointList[i].size(), 85 | _referencePointList[i][0]); 86 | } 87 | } 88 | 89 | std::vector CameraCalibrator::calculateChessboardReferencePoints() 90 | { 91 | std::vector cornerPoints = {}; 92 | for(unsigned int i = 0; i < this->_boardSize.width; ++i) { 93 | for(unsigned int j = 0; j < this->_boardSize.width; ++j) { 94 | // When using using a planar calibration pattern, we can omit z direction 95 | cv::Point3f point = cv::Point3f(j * this->_squareSizeInCm, 96 | i * this->_squareSizeInCm, 97 | 0); 98 | cornerPoints.push_back(point); 99 | } 100 | } 101 | return cornerPoints; 102 | } 103 | 104 | void CameraCalibrator::performCalibration() 105 | { 106 | std::cout << "Calibrating ..."; 107 | double reprojectionError = cv::calibrateCamera(this->_referencePointList, 108 | this->_measurementPointList, 109 | this->_imageSize, 110 | this->_cameraMatrix, 111 | this->_distortionCoefficientMatrix, 112 | this->_rotationVectors, 113 | this->_translationVectors); 114 | cv::calibrationMatrixValues(this->_cameraMatrix, 115 | this->_imageSize, 116 | this->_aperture[0], 117 | this->_aperture[1], 118 | this->_fieldOfViewInDegrees[0], 119 | this->_fieldOfViewInDegrees[1], 120 | this->_focalLength, 121 | this->_principalPointInMilliMeter, 122 | this->_aspectRatio); 123 | std::cout << "Calibrated Successfully." << std::endl; 124 | _isCalibrated = true; 125 | } 126 | 127 | cv::Mat CameraCalibrator::undistorImage(cv::Mat image) 128 | { 129 | cv::Mat imageUndistorted = image.clone(); 130 | cv::undistort(image, imageUndistorted, 131 | this->_cameraMatrix, 132 | this->_distortionCoefficientMatrix); 133 | cv::imshow("Undistorted image:", imageUndistorted); 134 | cv::waitKey(); 135 | return imageUndistorted; 136 | } 137 | 138 | cv::Vec2d CameraCalibrator::getAperture() 139 | { 140 | return this->_aperture; 141 | } 142 | 143 | cv::Vec2d CameraCalibrator::getFieldOfViewInDegrees() 144 | { 145 | return this->_fieldOfViewInDegrees; 146 | } 147 | 148 | double CameraCalibrator::getFocalLength() 149 | { 150 | return this->_focalLength; 151 | } 152 | 153 | cv::Point2d CameraCalibrator::getPrincipalPointInMillimeter() 154 | { 155 | return this->_principalPointInMilliMeter; 156 | } 157 | 158 | double CameraCalibrator::getAspectRatio() 159 | { 160 | return this->_aspectRatio; 161 | } 162 | 163 | std::vector CameraCalibrator::getRotationVectors() 164 | { 165 | return this->_rotationVectors; 166 | } 167 | 168 | std::vector CameraCalibrator::getTranslationVectors() 169 | { 170 | return this->_translationVectors; 171 | } 172 | 173 | std::vector CameraCalibrator::getReprojectionErrors() 174 | { 175 | return this->_reprojectionErrors; 176 | } 177 | 178 | cv::Mat CameraCalibrator::getDistortionCoefficientMatrix() 179 | { 180 | std::cout << this->_distortionCoefficientMatrix << std::endl; 181 | return this->_distortionCoefficientMatrix; 182 | } 183 | 184 | cv::Mat CameraCalibrator::getCameraMatrix() 185 | { 186 | return this->_cameraMatrix; 187 | } 188 | -------------------------------------------------------------------------------- /src/touchdesigner/OpenCVCameraCalibrationDAT.cpp: -------------------------------------------------------------------------------- 1 | /* Shared Use License: This file is owned by Derivative Inc. (Derivative) and 2 | * 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 (which 5 | * also govern the use of this file). You may share a modified version of this 6 | * file with another authorized licensee of Derivative's TouchDesigner software. 7 | * Otherwise, no redistribution or sharing of this file, with or without 8 | * modification, is permitted. 9 | */ 10 | 11 | #include "OpenCVCameraCalibrationDAT.hpp" 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include 19 | #include 20 | #include 21 | 22 | // These functions are basic C function, which the DLL loader can find 23 | // much easier than finding a C++ Class. 24 | // The DLLEXPORT prefix is needed so the compile exports these functions from the .dll 25 | // you are creating 26 | extern "C" 27 | { 28 | DLLEXPORT void FillDATPluginInfo(DAT_PluginInfo* info) 29 | { 30 | // Always return DAT_CPLUSPLUS_API_VERSION in this function. 31 | info->apiVersion = DATCPlusPlusAPIVersion; 32 | // The opType is the unique name for this TOP. It must start with a 33 | // capital A-Z character, and all the following characters must lower case 34 | // or numbers (a-z, 0-9) 35 | info->customOPInfo.opType->setString("OpenCVCameraCalibrationDAT"); 36 | // The opLabel is the text that will show up in the OP Create Dialog 37 | info->customOPInfo.opLabel->setString("OpenCV Camera Calibration DAT"); 38 | // Will be turned into a 3 letter icon on the nodes 39 | info->customOPInfo.opIcon->setString("OCC"); 40 | // Information about the author of this OP 41 | info->customOPInfo.authorName->setString("Guido Schmidt"); 42 | info->customOPInfo.authorEmail->setString("git@guidoschmidt.cc"); 43 | // This DAT works with 0 or 1 inputs 44 | info->customOPInfo.minInputs = 0; 45 | info->customOPInfo.maxInputs = 1; 46 | } 47 | 48 | DLLEXPORT DAT_CPlusPlusBase* CreateDATInstance(const OP_NodeInfo* info) 49 | { 50 | // Return a new instance of your class every time this is called. 51 | // It will be called once per DAT that is using the .dll 52 | return new CPlusPlusDATExample(info); 53 | } 54 | 55 | DLLEXPORT void DestroyDATInstance(DAT_CPlusPlusBase* instance) 56 | { 57 | // Delete the instance here, this will be called when 58 | // Touch is shutting down, when the DAT using that instance is deleted, or 59 | // if the DAT loads a different DLL 60 | delete (CPlusPlusDATExample*)instance; 61 | } 62 | 63 | }; 64 | 65 | CPlusPlusDATExample::CPlusPlusDATExample(const OP_NodeInfo* info) : myNodeInfo(info) 66 | { 67 | myExecuteCount = 0; 68 | myOffset = 0.0; 69 | myChop = ""; 70 | myChopChanName = ""; 71 | myChopChanVal = 0; 72 | _cameraCalibrator = new CameraCalibrator(); 73 | } 74 | 75 | CPlusPlusDATExample::~CPlusPlusDATExample() 76 | { 77 | } 78 | 79 | void CPlusPlusDATExample::getGeneralInfo(DAT_GeneralInfo* ginfo, 80 | const OP_Inputs* inputs, 81 | void* reserved1) 82 | { 83 | // This will cause the node to cook every frame 84 | ginfo->cookEveryFrameIfAsked = false; 85 | } 86 | 87 | void CPlusPlusDATExample::execute( 88 | DAT_Output* output, 89 | const OP_Inputs* inputs, 90 | void* reserved) 91 | { 92 | myExecuteCount++; 93 | if (inputs->getNumInputs() > 0) 94 | { 95 | if (_cameraCalibrator->isCalibrated()) { 96 | inputs->enablePar("Calibrate", false); 97 | // Status 98 | output->setTableSize(5, 5); 99 | output->setCellString(0, 0, "Status"); 100 | output->setCellString(1, 0, "Calibrated"); 101 | output->setCellString(2, 0, ""); 102 | output->setCellString(3, 0, ""); 103 | output->setCellString(4, 0, ""); 104 | // Focal length 105 | output->setCellString(0, 1, "Focal Length"); 106 | output->setCellDouble(1, 1, _cameraCalibrator->getFocalLength()); 107 | // Principal point 108 | output->setCellString(0, 2, "Principal Point"); 109 | output->setCellDouble(1, 2, _cameraCalibrator->getPrincipalPointInMillimeter().x); 110 | output->setCellDouble(2, 2, _cameraCalibrator->getPrincipalPointInMillimeter().y); 111 | // Distortion coefficients 112 | double ce0 = _cameraCalibrator->getDistortionCoefficientMatrix().at(0, 0); 113 | double ce1 = _cameraCalibrator->getDistortionCoefficientMatrix().at(1, 0); 114 | double ce2 = _cameraCalibrator->getDistortionCoefficientMatrix().at(2, 0); 115 | double ce3 = _cameraCalibrator->getDistortionCoefficientMatrix().at(3, 0); 116 | output->setCellString(0, 3, "Distortion Coefficients"); 117 | output->setCellDouble(1, 3, ce0); 118 | output->setCellDouble(2, 3, ce1); 119 | output->setCellDouble(3, 3, ce2); 120 | output->setCellDouble(4, 3, ce3); 121 | return; 122 | } 123 | else { 124 | inputs->enablePar("Calibrate", true); 125 | const OP_DATInput* input = inputs->getInputDAT(0); 126 | int numRows = input->numRows; 127 | int numCols = input->numCols; 128 | bool isTable = input->isTable; 129 | const char* str = input->getCell(0, 0); 130 | _cameraCalibrator->clearImageFiles(); 131 | for (unsigned int i = 0; i < numRows; ++i) { 132 | std::string imagePath = input->getCell(i, 1); 133 | _cameraCalibrator->addImageFile(imagePath); 134 | } 135 | std::vector imageFiles = _cameraCalibrator->getImageFiles(); 136 | output->setCellString(0, 0, "Input images"); 137 | output->setOutputDataType(DAT_OutDataType::Table); 138 | output->setTableSize(imageFiles.size() + 1, 1); 139 | for (int i = 0; i < imageFiles.size(); i++) { 140 | output->setCellString(i + 1, 0, imageFiles[i].c_str()); 141 | } 142 | } 143 | } 144 | else { 145 | inputs->enablePar("Calibrate", false); 146 | output->setTableSize(1, 1); 147 | output->setCellString(0, 0, "No input data"); 148 | } 149 | } 150 | 151 | int32_t CPlusPlusDATExample::getNumInfoCHOPChans(void* reserved1) 152 | { 153 | // We return the number of channel we want to output to any Info CHOP 154 | // connected to the CHOP. In this example we are just going to send one channel. 155 | return 0; 156 | } 157 | 158 | void CPlusPlusDATExample::getInfoCHOPChan(int32_t index, 159 | OP_InfoCHOPChan* chan, 160 | void* reserved1) 161 | { 162 | // This function will be called once for each channel we said we'd want to return 163 | // In this example it'll only be called once. 164 | if (index == 0) 165 | { 166 | chan->name->setString("executeCount"); 167 | chan->value = (float)myExecuteCount; 168 | } 169 | } 170 | 171 | bool CPlusPlusDATExample::getInfoDATSize(OP_InfoDATSize* infoSize, void* reserved1) 172 | { 173 | infoSize->rows = 3; 174 | infoSize->cols = 3; 175 | // Setting this to false means we'll be assigning values to the table 176 | // one row at a time. True means we'll do it one column at a time. 177 | infoSize->byColumn = false; 178 | return true; 179 | } 180 | 181 | void CPlusPlusDATExample::getInfoDATEntries(int32_t index, 182 | int32_t nEntries, 183 | OP_InfoDATEntries* entries, 184 | void* reserved1) 185 | { 186 | char tempBuffer[4096]; 187 | if (index == 0) 188 | { 189 | // Set the value for the first column 190 | #ifdef WIN32 191 | strcpy_s(tempBuffer, "executeCount"); 192 | #else // macOS 193 | strlcpy(tempBuffer, "executeCount", sizeof(tempBuffer)); 194 | #endif 195 | entries->values[0]->setString(tempBuffer); 196 | 197 | // Set the value for the second column 198 | #ifdef WIN32 199 | sprintf_s(tempBuffer, "%d", myExecuteCount); 200 | #else // macOS 201 | snprintf(tempBuffer, sizeof(tempBuffer), "%d", myExecuteCount); 202 | #endif 203 | entries->values[1]->setString(tempBuffer); 204 | } 205 | 206 | if (index == 1) 207 | { 208 | // Set the value for the first column 209 | #ifdef WIN32 210 | strcpy_s(tempBuffer, "offset"); 211 | #else // macOS 212 | strlcpy(tempBuffer, "offset", sizeof(tempBuffer)); 213 | #endif 214 | entries->values[0]->setString(tempBuffer); 215 | 216 | // Set the value for the second column 217 | #ifdef WIN32 218 | sprintf_s(tempBuffer, "%g", myOffset); 219 | #else // macOS 220 | snprintf(tempBuffer, sizeof(tempBuffer), "%g", myOffset); 221 | #endif 222 | entries->values[1]->setString(tempBuffer); 223 | } 224 | 225 | if (index == 2) 226 | { 227 | // Set the value for the first column 228 | #ifdef WIN32 229 | strcpy_s(tempBuffer, "DAT input name"); 230 | #else // macOS 231 | strlcpy(tempBuffer, "offset", sizeof(tempBuffer)); 232 | #endif 233 | entries->values[0]->setString(tempBuffer); 234 | 235 | // Set the value for the second column 236 | #ifdef WIN32 237 | strcpy_s(tempBuffer, myDat.c_str()); 238 | #else // macOS 239 | snprintf(tempBuffer, sizeof(tempBuffer), "%g", myOffset); 240 | #endif 241 | entries->values[1]->setString(tempBuffer); 242 | } 243 | } 244 | 245 | void CPlusPlusDATExample::setupParameters(OP_ParameterManager* manager, void* reserved1) 246 | { 247 | // Execute 248 | { 249 | OP_NumericParameter np; 250 | np.name = "Calibrate"; 251 | np.label = "Calibrate"; 252 | OP_ParAppendResult res = manager->appendPulse(np); 253 | assert(res == OP_ParAppendResult::Success); 254 | } 255 | } 256 | 257 | void CPlusPlusDATExample::performCalibrationAsync() 258 | { 259 | _cameraCalibrator->evaluateImageStack(); 260 | _cameraCalibrator->performCalibration(); 261 | } 262 | 263 | void CPlusPlusDATExample::pulsePressed(const char* name, void* reserved1) 264 | { 265 | if (!strcmp(name, "Calibrate")) 266 | { 267 | auto calculation_thread = std::async(&CPlusPlusDATExample::performCalibrationAsync, this); 268 | } 269 | } 270 | 271 | -------------------------------------------------------------------------------- /src/touchdesigner/DAT_CPlusPlusBase.h: -------------------------------------------------------------------------------- 1 | /* Shared Use License: This file is owned by Derivative Inc. (Derivative) and 2 | * 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 (which 5 | * also govern the use of this file). You may share a modified version of this 6 | * file with another authorized licensee of Derivative's TouchDesigner software. 7 | * Otherwise, no redistribution or sharing of this file, with or without 8 | * modification, is permitted. 9 | */ 10 | 11 | /* 12 | * Produced by: 13 | * 14 | * Derivative Inc 15 | * 401 Richmond Street West, Unit 386 16 | * Toronto, Ontario 17 | * Canada M5V 3A8 18 | * 416-591-3555 19 | * 20 | * NAME: DAT_CPlusPlusBase.h 21 | * 22 | * 23 | * Do not edit this file directly! 24 | * Make a subclass of DAT_CPlusPlusBase instead, and add your own 25 | * data/functions. 26 | 27 | * Derivative Developers:: Make sure the virtual function order 28 | * stays the same, otherwise changes won't be backwards compatible 29 | */ 30 | //#pragma once 31 | 32 | #ifndef __DAT_CPlusPlusBase__ 33 | #define __DAT_CPlusPlusBase__ 34 | 35 | #include 36 | #include "CPlusPlus_Common.h" 37 | 38 | 39 | class DAT_CPlusPlusBase; 40 | struct DAT_PluginInfo; 41 | 42 | 43 | // These are the definitions for the C-functions that are used to 44 | // load the library and create instances of the object you define 45 | typedef void(__cdecl *FILLDATPLUGININFO)(DAT_PluginInfo *info); 46 | typedef DAT_CPlusPlusBase* (__cdecl *CREATEDATINSTANCE)(const OP_NodeInfo*); 47 | typedef void(__cdecl *DESTROYDATINSTANCE)(DAT_CPlusPlusBase*); 48 | 49 | // Define for the current API version that this sample code is made for. 50 | // To upgrade to a newer version, replace the files 51 | // DAT_CPlusPlusBase.h 52 | // CPlusPlus_Common.h 53 | // from the samples folder in a newer TouchDesigner installation. 54 | // You may need to upgrade your plugin code in that case, to match 55 | // the new API requirements 56 | const int DATCPlusPlusAPIVersion = 2; 57 | 58 | struct DAT_PluginInfo 59 | { 60 | public: 61 | int32_t apiVersion = 0; 62 | 63 | private: 64 | int32_t reserved[100]; 65 | 66 | public: 67 | // Information used to describe this plugin as a custom OP. 68 | OP_CustomOPInfo customOPInfo; 69 | 70 | private: 71 | int32_t reserved2[20]; 72 | }; 73 | 74 | 75 | 76 | class DAT_GeneralInfo 77 | { 78 | public: 79 | // Set this to true if you want the DAT to cook every frame, even 80 | // if none of it's inputs/parameters are changing 81 | // DEFAULT: false 82 | 83 | bool cookEveryFrame; 84 | 85 | // Set this to true if you want the DAT to cook every frame, but only 86 | // if someone asks for it to cook. So if nobody is using the output from 87 | // the DAT, it won't cook. This is difereent from 'cookEveryFrame' 88 | // since that will cause it to cook every frame no matter what. 89 | 90 | bool cookEveryFrameIfAsked; 91 | 92 | private: 93 | int32_t reserved[20]; 94 | }; 95 | 96 | enum class DAT_OutDataType 97 | { 98 | Table = 0, 99 | Text, 100 | }; 101 | 102 | 103 | // CPU loading of Table: 104 | 105 | class DAT_Output 106 | { 107 | public: 108 | 109 | DAT_Output() 110 | { 111 | } 112 | 113 | ~DAT_Output() 114 | { 115 | } 116 | 117 | // Set the type of output data, call this function at the very start to 118 | // specify whether a Table or Text data will be output. 119 | virtual void setOutputDataType(DAT_OutDataType type) = 0; 120 | 121 | virtual DAT_OutDataType getOutputDataType() = 0; 122 | 123 | // If the type of out data is Table, set the number of rows and columns. 124 | virtual void setTableSize(const int32_t rows, const int32_t cols) = 0; 125 | 126 | virtual void getTableSize(int32_t *rows, int32_t *cols) = 0; 127 | 128 | // If the type of out data is set to Text, 129 | // Set the whole text by calling this function. str must be UTF-8 encoded. 130 | // returns false if null argument, 131 | // or if str is contains invalid UTF-8 bytes. 132 | virtual bool setText(const char* str) = 0; 133 | 134 | // Find the row/col index with a given name. name must be UTF-8 encoded. 135 | // The hintRowIndex/hintColIndex, if given and in range, will be 136 | // checked first to see if that row/col is a match. 137 | // This can make the searching faster if the row/col headers don't change often. 138 | // Returns -1 if it cannot find the row or if rowName isn't valid UTF-8. 139 | virtual int32_t findRow(const char* rowName, int32_t hint32_tRowIndex = -1) = 0; 140 | virtual int32_t findCol(const char* colName, int32_t hintColIndex = -1) = 0; 141 | 142 | // Set the string data for each cell of the table specified by a row and column index, 143 | // Returns false if such cell doesn't exists, or if str isn't valid UTF-8. 144 | virtual bool setCellString(int32_t row, int32_t col, const char* str) = 0; 145 | 146 | // Set the int data for each cell, similar to the setCellString() but sets Int values. 147 | virtual bool setCellInt(int32_t row, int32_t col, int32_t value) = 0; 148 | 149 | // Set the data for each cell, similar to the setCellString() but sets Double values. 150 | virtual bool setCellDouble(int32_t row, int32_t col, double value) = 0; 151 | 152 | 153 | // Get the string cell data at a row and column index. 154 | // Returns null if the cell/table doesn't exist. 155 | // The memory the pointer points to is valid until the next call to 156 | // a function that changes the tabel (setCell*, setTableSize etc.) 157 | // or the end of the ::execute function. 158 | virtual const char* getCellString(int32_t row, int32_t col) = 0; 159 | 160 | // Get the int32_t cell data with a row and column index, 161 | // returns false if it cannot find the cell, or invalid argument 162 | virtual bool getCellInt(int32_t row, int32_t col, int32_t* res) = 0; 163 | 164 | // Get the double cell data with a row and column index, 165 | // returns false if it cannot find the cell, or invalid argument 166 | virtual bool getCellDouble(int32_t row, int32_t col, double* res) = 0; 167 | 168 | 169 | private: 170 | 171 | int32_t reserved[20]; 172 | }; 173 | 174 | 175 | /*** DO NOT EDIT THIS CLASS, MAKE A SUBCLASS OF IT INSTEAD ***/ 176 | class DAT_CPlusPlusBase 177 | { 178 | 179 | protected: 180 | 181 | DAT_CPlusPlusBase() 182 | { 183 | } 184 | 185 | public: 186 | 187 | virtual 188 | ~DAT_CPlusPlusBase() 189 | { 190 | } 191 | 192 | // BEGIN PUBLIC INTERFACE 193 | 194 | // Some general settings can be assigned here (if you ovierride it) 195 | 196 | virtual void 197 | getGeneralInfo(DAT_GeneralInfo*, const OP_Inputs*, void* reserved1) 198 | { 199 | } 200 | 201 | 202 | // Add geometry data such as points, normals, colors, and triangles 203 | // or particles and etc. obtained from your desired algorithm or external files. 204 | // If the "directToGPU" flag is set to false, this function is being called 205 | // instead of executeVBO(). 206 | // See the OP_Inputs class definition for more details on it's contents 207 | virtual void execute(DAT_Output*, const OP_Inputs*, void* reserved1) = 0; 208 | 209 | 210 | // Override these methods if you want to output values to the Info CHOP/DAT 211 | // returning 0 means you dont plan to output any Info CHOP channels 212 | virtual int32_t 213 | getNumInfoCHOPChans(void *reserved1) 214 | { 215 | return 0; 216 | } 217 | 218 | // Specify the name and value for CHOP 'index', 219 | // by assigning something to 'name' and 'value' members of the 220 | // OP_InfoCHOPChan class pointer that is passed (it points 221 | // to a valid instance of the class already. 222 | // the 'name' pointer will initially point to nullptr 223 | // you must allocate memory or assign a constant string 224 | // to it. 225 | virtual void 226 | getInfoCHOPChan(int32_t index, OP_InfoCHOPChan* chan, void* reserved1) 227 | { 228 | } 229 | 230 | 231 | // Return false if you arn't returning data for an Info DAT 232 | // Return true if you are. 233 | // Set the members of the CHOP_InfoDATSize class to specify 234 | // the dimensions of the Info DAT 235 | virtual bool 236 | getInfoDATSize(OP_InfoDATSize* infoSize, void* reserved1) 237 | { 238 | return false; 239 | } 240 | 241 | 242 | // You are asked to assign values to the Info DAT 1 row or column at a time 243 | // The 'byColumn' variable in 'getInfoDATSize' is how you specify 244 | // if it is by column or by row. 245 | // 'index' is the row/column index 246 | // 'nEntries' is the number of entries in the row/column 247 | virtual void 248 | getInfoDATEntries(int32_t index, int32_t nEntries, 249 | OP_InfoDATEntries* entries, void* reserved1) 250 | { 251 | } 252 | 253 | 254 | // You can use this function to put the node into a warning state 255 | // with the returned string as the message. 256 | virtual void 257 | getWarningString(OP_String *warning, void *reserved1) 258 | { 259 | } 260 | 261 | // You can use this function to put the node into a error state 262 | // with the returned string as the message. 263 | virtual void 264 | getErrorString(OP_String *error, void *reserved1) 265 | { 266 | } 267 | 268 | // Use this function to return some text that will show up in the 269 | // info popup (when you middle click on a node) 270 | virtual void 271 | getInfoPopupString(OP_String *info, void *reserved1) 272 | { 273 | } 274 | 275 | 276 | // Override these methods if you want to define specfic parameters 277 | virtual void 278 | setupParameters(OP_ParameterManager* manager, void* reserved1) 279 | { 280 | } 281 | 282 | 283 | // This is called whenever a pulse parameter is pressed 284 | virtual void 285 | pulsePressed(const char* name, void* reserved1) 286 | { 287 | } 288 | 289 | // END PUBLIC INTERFACE 290 | 291 | 292 | private: 293 | 294 | // Reserved for future features 295 | virtual int32_t reservedFunc6() { return 0; } 296 | virtual int32_t reservedFunc7() { return 0; } 297 | virtual int32_t reservedFunc8() { return 0; } 298 | virtual int32_t reservedFunc9() { return 0; } 299 | virtual int32_t reservedFunc10() { return 0; } 300 | virtual int32_t reservedFunc11() { return 0; } 301 | virtual int32_t reservedFunc12() { return 0; } 302 | virtual int32_t reservedFunc13() { return 0; } 303 | virtual int32_t reservedFunc14() { return 0; } 304 | virtual int32_t reservedFunc15() { return 0; } 305 | virtual int32_t reservedFunc16() { return 0; } 306 | virtual int32_t reservedFunc17() { return 0; } 307 | virtual int32_t reservedFunc18() { return 0; } 308 | virtual int32_t reservedFunc19() { return 0; } 309 | virtual int32_t reservedFunc20() { return 0; } 310 | 311 | int32_t reserved[400]; 312 | 313 | }; 314 | 315 | static_assert(offsetof(DAT_PluginInfo, apiVersion) == 0, "Incorrect Alignment"); 316 | static_assert(offsetof(DAT_PluginInfo, customOPInfo) == 408, "Incorrect Alignment"); 317 | static_assert(sizeof(DAT_PluginInfo) == 944, "Incorrect Size"); 318 | 319 | static_assert(offsetof(DAT_GeneralInfo, cookEveryFrame) == 0, "Incorrect Alignment"); 320 | static_assert(offsetof(DAT_GeneralInfo, cookEveryFrameIfAsked) == 1, "Incorrect Alignment"); 321 | static_assert(sizeof(DAT_GeneralInfo) == 84, "Incorrect Size"); 322 | 323 | #endif 324 | -------------------------------------------------------------------------------- /src/touchdesigner/CPlusPlus_Common.h: -------------------------------------------------------------------------------- 1 | /* Shared Use License: This file is owned by Derivative Inc. (Derivative) and 2 | * 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 (which 5 | * also govern the use of this file). You may share a modified version of this 6 | * file with another authorized licensee of Derivative's TouchDesigner software. 7 | * Otherwise, no redistribution or sharing of this file, with or without 8 | * modification, is permitted. 9 | */ 10 | 11 | /* 12 | * Produced by: 13 | * 14 | * Derivative Inc 15 | * 401 Richmond Street West, Unit 386 16 | * Toronto, Ontario 17 | * Canada M5V 3A8 18 | * 416-591-3555 19 | * 20 | * NAME: CPlusPlus_Common.h 21 | * 22 | */ 23 | 24 | /******* 25 | Derivative Developers:: Make sure the virtual function order 26 | stays the same, otherwise changes won't be backwards compatible 27 | ********/ 28 | 29 | 30 | #ifndef __CPlusPlus_Common 31 | #define __CPlusPlus_Common 32 | 33 | 34 | #ifdef WIN32 35 | #define NOMINMAX 36 | #include 37 | #include 38 | #include "GL_Extensions.h" 39 | #define DLLEXPORT __declspec (dllexport) 40 | #else 41 | #include 42 | #define DLLEXPORT 43 | #endif 44 | 45 | #include 46 | #include 47 | #include 48 | 49 | struct cudaArray; 50 | 51 | enum class OP_CPUMemPixelType : int32_t 52 | { 53 | // 8-bit per color, BGRA pixels. This is preferred for 4 channel 8-bit data 54 | BGRA8Fixed = 0, 55 | // 8-bit per color, RGBA pixels. Only use this one if absolutely nesseary. 56 | RGBA8Fixed, 57 | // 32-bit float per color, RGBA pixels 58 | RGBA32Float, 59 | 60 | // Single and double channel options 61 | // Fixed 62 | R8Fixed, 63 | RG8Fixed, 64 | // Float 65 | R32Float, 66 | RG32Float, 67 | }; 68 | 69 | class OP_String; 70 | 71 | // Used to describe this Plugin so it can be used as a custom OP. 72 | // Can be filled in as part of the Fill*PluginInfo() callback 73 | class OP_CustomOPInfo 74 | { 75 | public: 76 | // For this plugin to be treated as a Custom OP, all of the below fields 77 | // must be filled in correctly. Otherwise the .dll can only be used 78 | // when manually loaded into the C++ TOP 79 | 80 | // The type name of the node, this needs to be unique from all the other 81 | // TOP plugins loaded on the system. The name must start with an upper case 82 | // character (A-Z), and the rest should be lower case 83 | // Only the characters a-z and 0-9 are allowed in the opType. 84 | // Spaces are not allowed 85 | OP_String* opType; 86 | 87 | // The english readable label for the node. This is what is show in the 88 | // OP Create Menu dialog. 89 | // Spaces and other special characters are allowed. 90 | // This can be a UTF-8 encoded string for non-english langauge label 91 | OP_String* opLabel; 92 | 93 | // This should be three letters (upper or lower case), or numbers, which 94 | // are used to create an icon for this Custom OP. 95 | OP_String* opIcon; 96 | 97 | // The minimum number of wired inputs required for this OP to function. 98 | int32_t minInputs = 0; 99 | 100 | // The maximum number of connected inputs allowed for this OP. If this plugin 101 | // always requires 1 input, then set both min and max to 1. 102 | int32_t maxInputs = 0; 103 | 104 | // The name of the author 105 | OP_String* authorName; 106 | 107 | // The email of the author 108 | OP_String* authorEmail; 109 | 110 | // Major version should be used to differentiate between drastically different 111 | // versions of this Custom OP. In particular changes that arn't backwards 112 | // compatible. 113 | // A project file will compare the major version of OPs saved in it with the 114 | // major version of the plugin installed on the system, and expect them to be 115 | // the same. 116 | int32_t majorVersion = 0; 117 | 118 | // Minor version is used to denote upgrades to a plugin. It should be increased 119 | // when new features are added to a plugin that would cause loading up a project 120 | // with an older version of the plguin to behavior incorrectly. For example 121 | // if new parameters are added to the plugin. 122 | // A project file will expect the plugin installed on the system to be greater than 123 | // or equal to the plugin version the project was created with. Assuming 124 | // the majorVersion is the same. 125 | int32_t minorVersion = 1; 126 | 127 | int32_t reserved[100]; 128 | }; 129 | 130 | 131 | class OP_NodeInfo 132 | { 133 | public: 134 | // The full path to the operator 135 | 136 | const char* opPath; 137 | 138 | // A unique ID representing the operator, no two operators will ever 139 | // have the same ID in a single TouchDesigner instance. 140 | 141 | uint32_t opId; 142 | 143 | // This is the handle to the main TouchDesigner window. 144 | // It's possible this will be 0 the first few times the operator cooks, 145 | // incase it cooks while TouchDesigner is still loading up 146 | 147 | #ifdef WIN32 148 | HWND mainWindowHandle; 149 | #endif 150 | 151 | int32_t reserved[19]; 152 | }; 153 | 154 | 155 | class OP_DATInput 156 | { 157 | public: 158 | const char* opPath; 159 | uint32_t opId; 160 | 161 | int32_t numRows; 162 | int32_t numCols; 163 | bool isTable; 164 | 165 | // data, referenced by (row,col), which will be a const char* for the 166 | // contents of the cell 167 | // E.g getCell(1,2) will be the contents of the cell located at (1,2) 168 | // The string will be in UTF-8 encoding. 169 | const char* 170 | getCell(int32_t row, int32_t col) const 171 | { 172 | return cellData[row * numCols + col]; 173 | } 174 | 175 | const char** cellData; 176 | 177 | // The number of times this node has cooked 178 | int64_t totalCooks; 179 | 180 | int32_t reserved[18]; 181 | }; 182 | 183 | 184 | class OP_TOPInput 185 | { 186 | public: 187 | const char* opPath; 188 | uint32_t opId; 189 | 190 | int32_t width; 191 | int32_t height; 192 | 193 | // You can use OP_Inputs::getTOPDataInCPUMemory() to download the 194 | // data from a TOP input into CPU memory easily. 195 | 196 | // The OpenGL Texture index for this TOP. 197 | // This is only valid when accessed from C++ TOPs. 198 | // Other C++ OPs will have this value set to 0 (invalid). 199 | GLuint textureIndex; 200 | 201 | // The OpenGL Texture target for this TOP. 202 | // E.g GL_TEXTURE_2D, GL_TEXTURE_CUBE, 203 | // GL_TEXTURE_2D_ARRAY 204 | GLenum textureType; 205 | 206 | // Depth for 3D and 2D_ARRAY textures, undefined 207 | // for other texture types 208 | uint32_t depth; 209 | 210 | // contains the internalFormat for the texture 211 | // such as GL_RGBA8, GL_RGBA32F, GL_R16 212 | GLint pixelFormat; 213 | 214 | int32_t reserved1; 215 | 216 | // When the TOP_ExecuteMode is CUDA, this will be filled in 217 | cudaArray* cudaInput; 218 | 219 | // The number of times this node has cooked 220 | int64_t totalCooks; 221 | 222 | int32_t reserved[14]; 223 | }; 224 | 225 | class OP_String 226 | { 227 | protected: 228 | OP_String() 229 | { 230 | } 231 | 232 | virtual ~OP_String() 233 | { 234 | } 235 | 236 | public: 237 | 238 | // val is expected to be UTF-8 encoded 239 | virtual void setString(const char* val) = 0; 240 | 241 | 242 | int32_t reserved[20]; 243 | 244 | }; 245 | 246 | 247 | class OP_CHOPInput 248 | { 249 | public: 250 | 251 | const char* opPath; 252 | uint32_t opId; 253 | 254 | int32_t numChannels; 255 | int32_t numSamples; 256 | double sampleRate; 257 | double startIndex; 258 | 259 | 260 | 261 | // Retrieve a float array for a specific channel. 262 | // 'i' ranges from 0 to numChannels-1 263 | // The returned arrray contains 'numSamples' samples. 264 | // e.g: getChannelData(1)[10] will refer to the 11th sample in the 2nd channel 265 | 266 | const float* 267 | getChannelData(int32_t i) const 268 | { 269 | return channelData[i]; 270 | } 271 | 272 | 273 | // Retrieve the name of a specific channel. 274 | // 'i' ranges from 0 to numChannels-1 275 | // For example getChannelName(1) is the name of the 2nd channel 276 | 277 | const char* 278 | getChannelName(int32_t i) const 279 | { 280 | return nameData[i]; 281 | } 282 | 283 | const float** channelData; 284 | const char** nameData; 285 | 286 | // The number of times this node has cooked 287 | int64_t totalCooks; 288 | 289 | int32_t reserved[18]; 290 | }; 291 | 292 | 293 | class OP_ObjectInput 294 | { 295 | public: 296 | 297 | const char* opPath; 298 | uint32_t opId; 299 | 300 | // Use these methods to calculate object transforms 301 | double worldTransform[4][4]; 302 | double localTransform[4][4]; 303 | 304 | // The number of times this node has cooked 305 | int64_t totalCooks; 306 | 307 | int32_t reserved[18]; 308 | }; 309 | 310 | 311 | // The type of data the attribute holds 312 | enum class AttribType : int32_t 313 | { 314 | // One or more floats 315 | Float = 0, 316 | 317 | // One or more integers 318 | Int, 319 | }; 320 | 321 | // Right now we only support point attributes. 322 | enum class AttribSet : int32_t 323 | { 324 | Invalid, 325 | Point = 0, 326 | }; 327 | 328 | // The type of the primitives, currently only Polygon type 329 | // is supported 330 | enum class PrimitiveType : int32_t 331 | { 332 | Invalid, 333 | Polygon = 0, 334 | }; 335 | 336 | 337 | class Vector 338 | { 339 | public: 340 | Vector() 341 | { 342 | x = 0.0f; 343 | y = 0.0f; 344 | z = 0.0f; 345 | } 346 | 347 | Vector(float xx, float yy, float zz) 348 | { 349 | x = xx; 350 | y = yy; 351 | z = zz; 352 | } 353 | 354 | // inplace operators 355 | inline Vector& 356 | operator*=(const float scalar) 357 | { 358 | x *= scalar; 359 | y *= scalar; 360 | z *= scalar; 361 | return *this; 362 | } 363 | 364 | inline Vector& 365 | operator/=(const float scalar) 366 | { 367 | x /= scalar; 368 | y /= scalar; 369 | z /= scalar; 370 | return *this; 371 | } 372 | 373 | inline Vector& 374 | operator-=(const Vector& trans) 375 | { 376 | x -= trans.x; 377 | y -= trans.y; 378 | z -= trans.z; 379 | return *this; 380 | } 381 | 382 | inline Vector& 383 | operator+=(const Vector& trans) 384 | { 385 | x += trans.x; 386 | y += trans.y; 387 | z += trans.z; 388 | return *this; 389 | } 390 | 391 | // non-inplace operations: 392 | inline Vector 393 | operator*(const float scalar) 394 | { 395 | Vector temp(*this); 396 | temp.x *= scalar; 397 | temp.y *= scalar; 398 | temp.z *= scalar; 399 | return temp; 400 | } 401 | 402 | inline Vector 403 | operator/(const float scalar) 404 | { 405 | Vector temp(*this); 406 | temp.x /= scalar; 407 | temp.y /= scalar; 408 | temp.z /= scalar; 409 | return temp; 410 | } 411 | 412 | inline Vector 413 | operator-(const Vector& trans) 414 | { 415 | Vector temp(*this); 416 | temp.x -= trans.x; 417 | temp.y -= trans.y; 418 | temp.z -= trans.z; 419 | return temp; 420 | } 421 | 422 | inline Vector 423 | operator+(const Vector& trans) 424 | { 425 | Vector temp(*this); 426 | temp.x += trans.x; 427 | temp.y += trans.y; 428 | temp.z += trans.z; 429 | return temp; 430 | } 431 | 432 | //------ 433 | float 434 | dot(const Vector &v) const 435 | { 436 | return x * v.x + y * v.y + z * v.z; 437 | } 438 | 439 | inline float 440 | length() 441 | { 442 | return sqrtf(dot(*this)); 443 | } 444 | 445 | inline float 446 | normalize() 447 | { 448 | float dn = x * x + y * y + z * z; 449 | if (dn > FLT_MIN && dn != 1.0F) 450 | { 451 | dn = sqrtf(dn); 452 | (*this) /= dn; 453 | } 454 | return dn; 455 | } 456 | 457 | float x; 458 | float y; 459 | float z; 460 | }; 461 | 462 | class Position 463 | { 464 | public: 465 | Position() 466 | { 467 | x = 0.0f; 468 | y = 0.0f; 469 | z = 0.0f; 470 | } 471 | 472 | Position(float xx, float yy, float zz) 473 | { 474 | x = xx; 475 | y = yy; 476 | z = zz; 477 | } 478 | 479 | // in-place operators 480 | inline Position& operator*=(const float scalar) 481 | { 482 | x *= scalar; 483 | y *= scalar; 484 | z *= scalar; 485 | return *this; 486 | } 487 | 488 | inline Position& operator/=(const float scalar) 489 | { 490 | x /= scalar; 491 | y /= scalar; 492 | z /= scalar; 493 | return *this; 494 | } 495 | 496 | inline Position& operator-=(const Vector& trans) 497 | { 498 | x -= trans.x; 499 | y -= trans.y; 500 | z -= trans.z; 501 | return *this; 502 | } 503 | 504 | inline Position& operator+=(const Vector& trans) 505 | { 506 | x += trans.x; 507 | y += trans.y; 508 | z += trans.z; 509 | return *this; 510 | } 511 | 512 | // non-inplace operators 513 | inline Position operator*(const float scalar) 514 | { 515 | Position temp(*this); 516 | temp.x *= scalar; 517 | temp.y *= scalar; 518 | temp.z *= scalar; 519 | return temp; 520 | } 521 | 522 | inline Position operator/(const float scalar) 523 | { 524 | Position temp(*this); 525 | temp.x /= scalar; 526 | temp.y /= scalar; 527 | temp.z /= scalar; 528 | return temp; 529 | } 530 | 531 | inline Position operator+(const Vector& trans) 532 | { 533 | Position temp(*this); 534 | temp.x += trans.x; 535 | temp.y += trans.y; 536 | temp.z += trans.z; 537 | return temp; 538 | } 539 | 540 | inline Position operator-(const Vector& trans) 541 | { 542 | Position temp(*this); 543 | temp.x -= trans.x; 544 | temp.y -= trans.y; 545 | temp.z -= trans.z; 546 | return temp; 547 | } 548 | 549 | float x; 550 | float y; 551 | float z; 552 | }; 553 | 554 | 555 | class Color 556 | { 557 | public: 558 | Color () 559 | { 560 | r = 1.0f; 561 | g = 1.0f; 562 | b = 1.0f; 563 | a = 1.0f; 564 | } 565 | 566 | Color (float rr, float gg, float bb, float aa) 567 | { 568 | r = rr; 569 | g = gg; 570 | b = bb; 571 | a = aa; 572 | } 573 | 574 | float r; 575 | float g; 576 | float b; 577 | float a; 578 | }; 579 | 580 | 581 | class TexCoord 582 | { 583 | public: 584 | TexCoord() 585 | { 586 | u = 0.0f; 587 | v = 0.0f; 588 | w = 0.0f; 589 | } 590 | 591 | TexCoord(float uu, float vv, float ww) 592 | { 593 | u = uu; 594 | v = vv; 595 | w = ww; 596 | } 597 | 598 | float u; 599 | float v; 600 | float w; 601 | }; 602 | 603 | class BoundingBox 604 | { 605 | public: 606 | BoundingBox(float minx, float miny, float minz, 607 | float maxx, float maxy, float maxz) : 608 | minX(minx), minY(miny), minZ(minz), maxX(maxx), maxY(maxy), maxZ(maxz) 609 | { 610 | } 611 | 612 | BoundingBox(const Position& min, const Position& max) 613 | { 614 | minX = min.x; 615 | maxX = max.x; 616 | minY = min.y; 617 | maxY = max.y; 618 | minZ = min.z; 619 | maxZ = max.z; 620 | } 621 | 622 | BoundingBox(const Position& center, float x, float y, float z) 623 | { 624 | minX = center.x - x; 625 | maxX = center.x + x; 626 | minY = center.y - y; 627 | maxY = center.y + y; 628 | minZ = center.z - z; 629 | maxZ = center.z + z; 630 | } 631 | 632 | // enlarge the bounding box by the input point Position 633 | void 634 | enlargeBounds(const Position& pos) 635 | { 636 | if (pos.x < minX) 637 | minX = pos.x; 638 | if (pos.x > maxX) 639 | maxX = pos.x; 640 | if (pos.y < minY) 641 | minY = pos.y; 642 | if (pos.y > maxY) 643 | maxY = pos.y; 644 | if (pos.z < minZ) 645 | minZ = pos.z; 646 | if (pos.z > maxZ) 647 | maxZ = pos.z; 648 | } 649 | 650 | // enlarge the bounding box by the input bounding box: 651 | void 652 | enlargeBounds(const BoundingBox &box) 653 | { 654 | if (box.minX < minX) 655 | minX = box.minX; 656 | if (box.maxX > maxX) 657 | maxX = box.maxX; 658 | if (box.minY < minY) 659 | minY = box.minY; 660 | if (box.maxY > maxY) 661 | maxY = box.maxY; 662 | if (box.minZ < minZ) 663 | minZ = box.minZ; 664 | if (box.maxZ > maxZ) 665 | maxZ = box.maxZ; 666 | } 667 | 668 | // returns the bounding box length in x axis: 669 | float 670 | sizeX() 671 | { 672 | return maxX - minX; 673 | } 674 | 675 | // returns the bounding box length in y axis: 676 | float 677 | sizeY() 678 | { 679 | return maxY - minY; 680 | } 681 | 682 | // returns the bounding box length in z axis: 683 | float 684 | sizeZ() 685 | { 686 | return maxZ - minZ; 687 | } 688 | 689 | bool 690 | getCenter(Position* pos) 691 | { 692 | if (!pos) 693 | return false; 694 | pos->x = (minX + maxX) / 2.0f; 695 | pos->y = (minY + maxY) / 2.0f; 696 | pos->z = (minZ + maxZ) / 2.0f; 697 | return true; 698 | } 699 | 700 | // verifies if the input position (pos) is inside the current bounding box or not: 701 | bool 702 | isInside(const Position& pos) 703 | { 704 | if (pos.x >= minX && pos.x <= maxX && 705 | pos.y >= minY && pos.y <= maxY && 706 | pos.z >= minZ && pos.z <= maxZ) 707 | return true; 708 | else 709 | return false; 710 | } 711 | 712 | 713 | float minX; 714 | float minY; 715 | float minZ; 716 | 717 | float maxX; 718 | float maxY; 719 | float maxZ; 720 | 721 | }; 722 | 723 | 724 | class SOP_NormalInfo 725 | { 726 | public: 727 | 728 | SOP_NormalInfo() 729 | { 730 | numNormals = 0; 731 | attribSet = AttribSet::Point; 732 | normals = nullptr; 733 | } 734 | 735 | int32_t numNormals; 736 | AttribSet attribSet; 737 | const Vector* normals; 738 | }; 739 | 740 | class SOP_ColorInfo 741 | { 742 | public: 743 | 744 | SOP_ColorInfo() 745 | { 746 | numColors = 0; 747 | attribSet = AttribSet::Point; 748 | colors = nullptr; 749 | } 750 | 751 | int32_t numColors; 752 | AttribSet attribSet; 753 | const Color* colors; 754 | }; 755 | 756 | class SOP_TextureInfo 757 | { 758 | public: 759 | 760 | SOP_TextureInfo() 761 | { 762 | numTextures = 0; 763 | attribSet = AttribSet::Point; 764 | textures = nullptr; 765 | numTextureLayers = 0; 766 | } 767 | 768 | int32_t numTextures; 769 | AttribSet attribSet; 770 | const TexCoord* textures; 771 | int32_t numTextureLayers; 772 | }; 773 | 774 | 775 | 776 | // CustomAttribInfo, all the required data for each custom attribute 777 | // this info can be queried by calling getCustomAttribute() which accepts 778 | // two types of argument: 779 | // 1) a valid index of a custom attribute 780 | // 2) a valid name of a custom attribute 781 | class SOP_CustomAttribInfo 782 | { 783 | public: 784 | 785 | SOP_CustomAttribInfo() 786 | { 787 | name = nullptr; 788 | numComponents = 0; 789 | attribType = AttribType::Float; 790 | } 791 | 792 | SOP_CustomAttribInfo(const char* n, int32_t numComp, const AttribType& type) 793 | { 794 | name = n; 795 | numComponents = numComp; 796 | attribType = type; 797 | } 798 | 799 | const char* name; 800 | int32_t numComponents; 801 | AttribType attribType; 802 | }; 803 | 804 | // SOP_CustomAttribData, all the required data for each custom attribute 805 | // this info can be queried by calling getCustomAttribute() which accepts 806 | // a valid name of a custom attribute 807 | class SOP_CustomAttribData : public SOP_CustomAttribInfo 808 | { 809 | public: 810 | 811 | SOP_CustomAttribData() 812 | { 813 | name = nullptr; 814 | numComponents = 0; 815 | attribType = AttribType::Float; 816 | floatData = nullptr; 817 | intData = nullptr; 818 | } 819 | 820 | SOP_CustomAttribData(const char* n, int32_t numComp, const AttribType& type) 821 | { 822 | name = n; 823 | numComponents = numComp; 824 | attribType = type; 825 | floatData = nullptr; 826 | intData = nullptr; 827 | } 828 | 829 | const float* floatData; 830 | const int32_t* intData; 831 | 832 | }; 833 | 834 | // SOP_PrimitiveInfo, all the required data for each primitive 835 | // this info can be queried by calling getPrimitive() which accepts 836 | // a valid index of a primitive as an input argument 837 | class SOP_PrimitiveInfo 838 | { 839 | public: 840 | 841 | SOP_PrimitiveInfo() 842 | { 843 | pointIndices = nullptr; 844 | numVertices = 0; 845 | type = PrimitiveType::Invalid; 846 | pointIndicesOffset = 0; 847 | } 848 | 849 | // number of vertices of this prim 850 | int32_t numVertices; 851 | 852 | // all the indices of the vertices of the primitive. This array has 853 | // numVertices entries in it 854 | const int32_t* pointIndices; 855 | 856 | // The type of this primitive 857 | PrimitiveType type; 858 | 859 | // the offset of the this primitive's point indices in the index array 860 | // returned from getAllPrimPointIndices() 861 | int32_t pointIndicesOffset; 862 | 863 | }; 864 | 865 | 866 | 867 | 868 | class OP_SOPInput 869 | { 870 | public: 871 | 872 | virtual ~OP_SOPInput() 873 | { 874 | } 875 | 876 | 877 | 878 | const char* opPath; 879 | uint32_t opId; 880 | 881 | 882 | // Returns the total number of points 883 | virtual int32_t getNumPoints() const = 0; 884 | 885 | // The total number of vertices, across all primitives. 886 | virtual int32_t getNumVertices() const = 0; 887 | 888 | // The total number of primitives 889 | virtual int32_t getNumPrimitives() const = 0; 890 | 891 | // The total number of custom attributes 892 | virtual int32_t getNumCustomAttributes() const = 0; 893 | 894 | // Returns an array of point positions. This array is getNumPoints() long. 895 | virtual const Position* getPointPositions() const = 0; 896 | 897 | // Returns an array of normals. 898 | // 899 | // Returns nullptr if no normals are present 900 | virtual const SOP_NormalInfo* getNormals() const = 0; 901 | 902 | // Returns an array of colors. 903 | // Returns nullptr if no colors are present 904 | virtual const SOP_ColorInfo* getColors() const = 0; 905 | 906 | // Returns an array of texture coordinates. 907 | // If multiple texture coordinate layers are present, they will be placed 908 | // interleaved back-to-back. 909 | // E.g layer0 followed by layer1 followed by layer0 etc. 910 | // 911 | // Returns nullptr if no texture layers are present 912 | virtual const SOP_TextureInfo* getTextures() const = 0; 913 | 914 | // Returns the custom attribute data with an input index 915 | virtual const SOP_CustomAttribData* getCustomAttribute(int32_t customAttribIndex) const = 0; 916 | 917 | // Returns the custom attribute data with its name 918 | virtual const SOP_CustomAttribData* getCustomAttribute(const char* customAttribName) const = 0; 919 | 920 | // Returns true if the SOP has a normal attribute of the given source 921 | // attribute 'N' 922 | virtual bool hasNormals() const = 0; 923 | 924 | // Returns true if the SOP has a color the given source 925 | // attribute 'Cd' 926 | virtual bool hasColors() const = 0; 927 | 928 | // Returns the SOP_PrimitiveInfo with primIndex 929 | const SOP_PrimitiveInfo 930 | getPrimitive(int32_t primIndex) const 931 | { 932 | return myPrimsInfo[primIndex]; 933 | } 934 | 935 | // Returns the full list of all the point indices for all primitives. 936 | // The primitives are stored back to back in this array. 937 | // This is a faster but harder way to work with primitives than 938 | // getPrimPointIndices() 939 | const int32_t* 940 | getAllPrimPointIndices() 941 | { 942 | return myPrimPointIndices; 943 | } 944 | 945 | SOP_PrimitiveInfo* myPrimsInfo; 946 | const int32_t* myPrimPointIndices; 947 | 948 | // The number of times this node has cooked 949 | int64_t totalCooks; 950 | 951 | int32_t reserved[98]; 952 | }; 953 | 954 | 955 | 956 | enum class OP_TOPInputDownloadType : int32_t 957 | { 958 | // The texture data will be downloaded and and available on the next frame. 959 | // Except for the first time this is used, getTOPDataInCPUMemory() 960 | // will return the texture data on the CPU from the previous frame. 961 | // The first getTOPDataInCPUMemory() is called it will be nullptr. 962 | // ** This mode should be used is most cases for performance reasons ** 963 | Delayed = 0, 964 | 965 | // The texture data will be downloaded immediately and be available 966 | // this frame. This can cause a large stall though and should be avoided 967 | // in most cases 968 | Instant, 969 | }; 970 | 971 | class OP_TOPInputDownloadOptions 972 | { 973 | public: 974 | OP_TOPInputDownloadOptions() 975 | { 976 | downloadType = OP_TOPInputDownloadType::Delayed; 977 | verticalFlip = false; 978 | cpuMemPixelType = OP_CPUMemPixelType::BGRA8Fixed; 979 | } 980 | 981 | OP_TOPInputDownloadType downloadType; 982 | 983 | // Set this to true if you want the image vertically flipped in the 984 | // downloaded data 985 | bool verticalFlip; 986 | 987 | // Set this to how you want the pixel data to be give to you in CPU 988 | // memory. BGRA8Fixed should be used for 4 channel 8-bit data if possible 989 | OP_CPUMemPixelType cpuMemPixelType; 990 | 991 | }; 992 | 993 | 994 | class OP_Inputs 995 | { 996 | public: 997 | // NOTE: When writting a TOP, none of these functions should 998 | // be called inside a beginGLCommands()/endGLCommands() section 999 | // as they may require GL themselves to complete execution. 1000 | 1001 | // these are wired into the node 1002 | virtual int32_t getNumInputs() const = 0; 1003 | 1004 | // may return nullptr when invalid input 1005 | // only valid for C++ TOP operators 1006 | virtual const OP_TOPInput* getInputTOP(int32_t index) const = 0; 1007 | // only valid for C++ CHOP operators 1008 | virtual const OP_CHOPInput* getInputCHOP(int32_t index) const = 0; 1009 | // getInputSOP() declared later on in the class 1010 | // getInputDAT() declared later on in the class 1011 | 1012 | // these are defined by parameters. 1013 | // may return nullptr when invalid input 1014 | // this value is valid until the parameters are rebuilt or it is called with the same parameter name. 1015 | virtual const OP_DATInput* getParDAT(const char *name) const = 0; 1016 | virtual const OP_TOPInput* getParTOP(const char *name) const = 0; 1017 | virtual const OP_CHOPInput* getParCHOP(const char *name) const = 0; 1018 | virtual const OP_ObjectInput* getParObject(const char *name) const = 0; 1019 | // getParSOP() declared later on in the class 1020 | 1021 | // these work on any type of parameter and can be interchanged 1022 | // for menu types, int returns the menu selection index, string returns the item 1023 | 1024 | // returns the requested value, index may be 0 to 4. 1025 | virtual double getParDouble(const char* name, int32_t index = 0) const = 0; 1026 | 1027 | // for multiple values: returns True on success/false otherwise 1028 | virtual bool getParDouble2(const char* name, double &v0, double &v1) const = 0; 1029 | virtual bool getParDouble3(const char* name, double &v0, double &v1, double &v2) const = 0; 1030 | virtual bool getParDouble4(const char* name, double &v0, double &v1, double &v2, double &v3) const = 0; 1031 | 1032 | 1033 | // returns the requested value 1034 | virtual int32_t getParInt(const char* name, int32_t index = 0) const = 0; 1035 | 1036 | // for multiple values: returns True on success/false otherwise 1037 | virtual bool getParInt2(const char* name, int32_t &v0, int32_t &v1) const = 0; 1038 | virtual bool getParInt3(const char* name, int32_t &v0, int32_t &v1, int32_t &v2) const = 0; 1039 | virtual bool getParInt4(const char* name, int32_t &v0, int32_t &v1, int32_t &v2, int32_t &v3) const = 0; 1040 | 1041 | // returns the requested value 1042 | // this value is valid until the parameters are rebuilt or it is called with the same parameter name. 1043 | // return value usable for life of parameter 1044 | // The returned string will be in UTF-8 encoding. 1045 | virtual const char* getParString(const char* name) const = 0; 1046 | 1047 | 1048 | // this is similar to getParString, but will return an absolute path if it exists, with 1049 | // slash direction consistent with O/S requirements. 1050 | // to get the original parameter value, use getParString 1051 | // return value usable for life of parameter 1052 | // The returned string will be in UTF-8 encoding. 1053 | virtual const char* getParFilePath(const char* name) const = 0; 1054 | 1055 | // returns true on success 1056 | // from_name and to_name must be Object parameters 1057 | virtual bool getRelativeTransform(const char* from_name, const char* to_name, double matrix[4][4]) const = 0; 1058 | 1059 | 1060 | // disable or enable updating of the parameter 1061 | virtual void enablePar(const char* name, bool onoff) const = 0; 1062 | 1063 | 1064 | // these are defined by paths. 1065 | // may return nullptr when invalid input 1066 | // this value is valid until the parameters are rebuilt or it is called with the same parameter name. 1067 | virtual const OP_DATInput* getDAT(const char *path) const = 0; 1068 | virtual const OP_TOPInput* getTOP(const char *path) const = 0; 1069 | virtual const OP_CHOPInput* getCHOP(const char *path) const = 0; 1070 | virtual const OP_ObjectInput* getObject(const char *path) const = 0; 1071 | 1072 | 1073 | // This function can be used to retrieve the TOPs texture data in CPU 1074 | // memory. You must pass the OP_TOPInput object you get from 1075 | // getParTOP/getInputTOP into this, not a copy you've made 1076 | // 1077 | // Fill in a OP_TOPIputDownloadOptions class with the desired options set 1078 | // 1079 | // Returns the data, which will be valid until the end of execute() 1080 | // Returned value may be nullptr in some cases, such as the first call 1081 | // to this with options->downloadType == OP_TOP_DOWNLOAD_DELAYED. 1082 | virtual void* getTOPDataInCPUMemory(const OP_TOPInput *top, 1083 | const OP_TOPInputDownloadOptions *options) const = 0; 1084 | 1085 | 1086 | virtual const OP_SOPInput* getParSOP(const char *name) const = 0; 1087 | // only valid for C++ SOP operators 1088 | virtual const OP_SOPInput* getInputSOP(int32_t index) const = 0; 1089 | virtual const OP_SOPInput* getSOP(const char *path) const = 0; 1090 | 1091 | // only valid for C++ DAT operators 1092 | virtual const OP_DATInput* getInputDAT(int32_t index) const = 0; 1093 | 1094 | }; 1095 | 1096 | class OP_InfoCHOPChan 1097 | { 1098 | public: 1099 | OP_String* name; 1100 | float value; 1101 | 1102 | int32_t reserved[10]; 1103 | }; 1104 | 1105 | 1106 | class OP_InfoDATSize 1107 | { 1108 | public: 1109 | 1110 | // Set this to the size you want the table to be 1111 | 1112 | int32_t rows; 1113 | int32_t cols; 1114 | 1115 | // Set this to true if you want to return DAT entries on a column 1116 | // by column basis. 1117 | // Otherwise set to false, and you'll be expected to set them on 1118 | // a row by row basis. 1119 | // DEFAULT : false 1120 | 1121 | bool byColumn; 1122 | 1123 | int32_t reserved[10]; 1124 | }; 1125 | 1126 | 1127 | class OP_InfoDATEntries 1128 | { 1129 | public: 1130 | 1131 | // This is an array of OP_String* pointers which you are expected to assign 1132 | // values to. 1133 | // e.g values[1]->setString("myColumnName"); 1134 | // The string should be in UTF-8 encoding. 1135 | OP_String** values; 1136 | 1137 | int32_t reserved[10]; 1138 | }; 1139 | 1140 | 1141 | class OP_NumericParameter 1142 | { 1143 | public: 1144 | 1145 | OP_NumericParameter(const char* iname = nullptr) 1146 | { 1147 | name = iname; 1148 | label = page = nullptr; 1149 | 1150 | for (int i = 0; i<4; i++) 1151 | { 1152 | defaultValues[i] = 0.0; 1153 | 1154 | minSliders[i] = 0.0; 1155 | maxSliders[i] = 1.0; 1156 | 1157 | minValues[i] = 0.0; 1158 | maxValues[i] = 1.0; 1159 | 1160 | clampMins[i] = false; 1161 | clampMaxes[i] = false; 1162 | } 1163 | } 1164 | 1165 | // Any char* values passed are copied immediately by the append parameter functions, 1166 | // and do not need to be retained by the calling function. 1167 | // Must begin with capital letter, and contain no spaces 1168 | const char* name; 1169 | const char* label; 1170 | const char* page; 1171 | 1172 | double defaultValues[4]; 1173 | double minValues[4]; 1174 | double maxValues[4]; 1175 | 1176 | bool clampMins[4]; 1177 | bool clampMaxes[4]; 1178 | 1179 | double minSliders[4]; 1180 | double maxSliders[4]; 1181 | 1182 | int32_t reserved[20]; 1183 | 1184 | }; 1185 | 1186 | 1187 | class OP_StringParameter 1188 | { 1189 | public: 1190 | 1191 | OP_StringParameter(const char* iname = nullptr) 1192 | { 1193 | name = iname; 1194 | label = page = nullptr; 1195 | defaultValue = nullptr; 1196 | } 1197 | 1198 | // Any char* values passed are copied immediately by the append parameter functions, 1199 | // and do not need to be retained by the calling function. 1200 | 1201 | // Must begin with capital letter, and contain no spaces 1202 | const char* name; 1203 | const char* label; 1204 | const char* page; 1205 | 1206 | // This should be in UTF-8 encoding. 1207 | const char* defaultValue; 1208 | 1209 | int32_t reserved[20]; 1210 | }; 1211 | 1212 | 1213 | enum class OP_ParAppendResult : int32_t 1214 | { 1215 | Success = 0, 1216 | InvalidName, // invalid or duplicate name 1217 | InvalidSize, // size out of range 1218 | }; 1219 | 1220 | 1221 | class OP_ParameterManager 1222 | { 1223 | 1224 | public: 1225 | 1226 | // Returns PARAMETER_APPEND_SUCCESS on succesful 1227 | 1228 | virtual OP_ParAppendResult appendFloat(const OP_NumericParameter &np, int32_t size = 1) = 0; 1229 | virtual OP_ParAppendResult appendInt(const OP_NumericParameter &np, int32_t size = 1) = 0; 1230 | 1231 | virtual OP_ParAppendResult appendXY(const OP_NumericParameter &np) = 0; 1232 | virtual OP_ParAppendResult appendXYZ(const OP_NumericParameter &np) = 0; 1233 | 1234 | virtual OP_ParAppendResult appendUV(const OP_NumericParameter &np) = 0; 1235 | virtual OP_ParAppendResult appendUVW(const OP_NumericParameter &np) = 0; 1236 | 1237 | virtual OP_ParAppendResult appendRGB(const OP_NumericParameter &np) = 0; 1238 | virtual OP_ParAppendResult appendRGBA(const OP_NumericParameter &np) = 0; 1239 | 1240 | virtual OP_ParAppendResult appendToggle(const OP_NumericParameter &np) = 0; 1241 | virtual OP_ParAppendResult appendPulse(const OP_NumericParameter &np) = 0; 1242 | 1243 | virtual OP_ParAppendResult appendString(const OP_StringParameter &sp) = 0; 1244 | virtual OP_ParAppendResult appendFile(const OP_StringParameter &sp) = 0; 1245 | virtual OP_ParAppendResult appendFolder(const OP_StringParameter &sp) = 0; 1246 | 1247 | virtual OP_ParAppendResult appendDAT(const OP_StringParameter &sp) = 0; 1248 | virtual OP_ParAppendResult appendCHOP(const OP_StringParameter &sp) = 0; 1249 | virtual OP_ParAppendResult appendTOP(const OP_StringParameter &sp) = 0; 1250 | virtual OP_ParAppendResult appendObject(const OP_StringParameter &sp) = 0; 1251 | // appendSOP() located further down in the class 1252 | 1253 | 1254 | // Any char* values passed are copied immediately by the append parameter functions, 1255 | // and do not need to be retained by the calling function. 1256 | virtual OP_ParAppendResult appendMenu(const OP_StringParameter &sp, 1257 | int32_t nitems, const char **names, 1258 | const char **labels) = 0; 1259 | 1260 | // Any char* values passed are copied immediately by the append parameter functions, 1261 | // and do not need to be retained by the calling function. 1262 | virtual OP_ParAppendResult appendStringMenu(const OP_StringParameter &sp, 1263 | int32_t nitems, const char **names, 1264 | const char **labels) = 0; 1265 | 1266 | virtual OP_ParAppendResult appendSOP(const OP_StringParameter &sp) = 0; 1267 | 1268 | 1269 | }; 1270 | 1271 | static_assert(offsetof(OP_CustomOPInfo, opType) == 0, "Incorrect Alignment"); 1272 | static_assert(offsetof(OP_CustomOPInfo, opLabel) == 8, "Incorrect Alignment"); 1273 | static_assert(offsetof(OP_CustomOPInfo, opIcon) == 16, "Incorrect Alignment"); 1274 | static_assert(offsetof(OP_CustomOPInfo, minInputs) == 24, "Incorrect Alignment"); 1275 | static_assert(offsetof(OP_CustomOPInfo, maxInputs) == 28, "Incorrect Alignment"); 1276 | static_assert(offsetof(OP_CustomOPInfo, authorName) == 32, "Incorrect Alignment"); 1277 | static_assert(offsetof(OP_CustomOPInfo, authorEmail) == 40, "Incorrect Alignment"); 1278 | static_assert(offsetof(OP_CustomOPInfo, majorVersion) == 48, "Incorrect Alignment"); 1279 | static_assert(offsetof(OP_CustomOPInfo, minorVersion) == 52, "Incorrect Alignment"); 1280 | static_assert(sizeof(OP_CustomOPInfo) == 456, "Incorrect Size"); 1281 | 1282 | static_assert(offsetof(OP_NodeInfo, opPath) == 0, "Incorrect Alignment"); 1283 | static_assert(offsetof(OP_NodeInfo, opId) == 8, "Incorrect Alignment"); 1284 | #ifdef WIN32 1285 | static_assert(offsetof(OP_NodeInfo, mainWindowHandle) == 16, "Incorrect Alignment"); 1286 | static_assert(sizeof(OP_NodeInfo) == 104, "Incorrect Size"); 1287 | #else 1288 | static_assert(sizeof(OP_NodeInfo) == 88, "Incorrect Size"); 1289 | #endif 1290 | 1291 | static_assert(offsetof(OP_DATInput, opPath) == 0, "Incorrect Alignment"); 1292 | static_assert(offsetof(OP_DATInput, opId) == 8, "Incorrect Alignment"); 1293 | static_assert(offsetof(OP_DATInput, numRows) == 12, "Incorrect Alignment"); 1294 | static_assert(offsetof(OP_DATInput, numCols) == 16, "Incorrect Alignment"); 1295 | static_assert(offsetof(OP_DATInput, isTable) == 20, "Incorrect Alignment"); 1296 | static_assert(offsetof(OP_DATInput, cellData) == 24, "Incorrect Alignment"); 1297 | static_assert(offsetof(OP_DATInput, totalCooks) == 32, "Incorrect Alignment"); 1298 | static_assert(sizeof(OP_DATInput) == 112, "Incorrect Size"); 1299 | 1300 | static_assert(offsetof(OP_TOPInput, opPath) == 0, "Incorrect Alignment"); 1301 | static_assert(offsetof(OP_TOPInput, opId) == 8, "Incorrect Alignment"); 1302 | static_assert(offsetof(OP_TOPInput, width) == 12, "Incorrect Alignment"); 1303 | static_assert(offsetof(OP_TOPInput, height) == 16, "Incorrect Alignment"); 1304 | static_assert(offsetof(OP_TOPInput, textureIndex) == 20, "Incorrect Alignment"); 1305 | static_assert(offsetof(OP_TOPInput, textureType) == 24, "Incorrect Alignment"); 1306 | static_assert(offsetof(OP_TOPInput, depth) == 28, "Incorrect Alignment"); 1307 | static_assert(offsetof(OP_TOPInput, pixelFormat) == 32, "Incorrect Alignment"); 1308 | static_assert(offsetof(OP_TOPInput, cudaInput) == 40, "Incorrect Alignment"); 1309 | static_assert(offsetof(OP_TOPInput, totalCooks) == 48, "Incorrect Alignment"); 1310 | static_assert(sizeof(OP_TOPInput) == 112, "Incorrect Size"); 1311 | 1312 | static_assert(offsetof(OP_CHOPInput, opPath) == 0, "Incorrect Alignment"); 1313 | static_assert(offsetof(OP_CHOPInput, opId) == 8, "Incorrect Alignment"); 1314 | static_assert(offsetof(OP_CHOPInput, numChannels) == 12, "Incorrect Alignment"); 1315 | static_assert(offsetof(OP_CHOPInput, numSamples) == 16, "Incorrect Alignment"); 1316 | static_assert(offsetof(OP_CHOPInput, sampleRate) == 24, "Incorrect Alignment"); 1317 | static_assert(offsetof(OP_CHOPInput, startIndex) == 32, "Incorrect Alignment"); 1318 | static_assert(offsetof(OP_CHOPInput, channelData) == 40, "Incorrect Alignment"); 1319 | static_assert(offsetof(OP_CHOPInput, nameData) == 48, "Incorrect Alignment"); 1320 | static_assert(offsetof(OP_CHOPInput, totalCooks) == 56, "Incorrect Alignment"); 1321 | static_assert(sizeof(OP_CHOPInput) == 136, "Incorrect Size"); 1322 | 1323 | static_assert(offsetof(OP_ObjectInput, opPath) == 0, "Incorrect Alignment"); 1324 | static_assert(offsetof(OP_ObjectInput, opId) == 8, "Incorrect Alignment"); 1325 | static_assert(offsetof(OP_ObjectInput, worldTransform) == 16, "Incorrect Alignment"); 1326 | static_assert(offsetof(OP_ObjectInput, localTransform) == 144, "Incorrect Alignment"); 1327 | static_assert(offsetof(OP_ObjectInput, totalCooks) == 272, "Incorrect Alignment"); 1328 | static_assert(sizeof(OP_ObjectInput) == 352, "Incorrect Size"); 1329 | 1330 | static_assert(offsetof(Position, x) == 0, "Incorrect Alignment"); 1331 | static_assert(offsetof(Position, y) == 4, "Incorrect Alignment"); 1332 | static_assert(offsetof(Position, z) == 8, "Incorrect Alignment"); 1333 | static_assert(sizeof(Position) == 12, "Incorrect Size"); 1334 | 1335 | static_assert(offsetof(Vector, x) == 0, "Incorrect Alignment"); 1336 | static_assert(offsetof(Vector, y) == 4, "Incorrect Alignment"); 1337 | static_assert(offsetof(Vector, z) == 8, "Incorrect Alignment"); 1338 | static_assert(sizeof(Vector) == 12, "Incorrect Size"); 1339 | 1340 | static_assert(offsetof(Color, r) == 0, "Incorrect Alignment"); 1341 | static_assert(offsetof(Color, g) == 4, "Incorrect Alignment"); 1342 | static_assert(offsetof(Color, b) == 8, "Incorrect Alignment"); 1343 | static_assert(offsetof(Color, a) == 12, "Incorrect Alignment"); 1344 | static_assert(sizeof(Color) == 16, "Incorrect Size"); 1345 | 1346 | static_assert(offsetof(TexCoord, u) == 0, "Incorrect Alignment"); 1347 | static_assert(offsetof(TexCoord, v) == 4, "Incorrect Alignment"); 1348 | static_assert(offsetof(TexCoord, w) == 8, "Incorrect Alignment"); 1349 | static_assert(sizeof(TexCoord) == 12, "Incorrect Size"); 1350 | 1351 | static_assert(offsetof(SOP_NormalInfo, numNormals) == 0, "Incorrect Alignment"); 1352 | static_assert(offsetof(SOP_NormalInfo, attribSet) == 4, "Incorrect Alignment"); 1353 | static_assert(offsetof(SOP_NormalInfo, normals) == 8, "Incorrect Alignment"); 1354 | static_assert(sizeof(SOP_NormalInfo) == 16, "Incorrect Size"); 1355 | 1356 | static_assert(offsetof(SOP_ColorInfo, numColors) == 0, "Incorrect Alignment"); 1357 | static_assert(offsetof(SOP_ColorInfo, attribSet) == 4, "Incorrect Alignment"); 1358 | static_assert(offsetof(SOP_ColorInfo, colors) == 8, "Incorrect Alignment"); 1359 | static_assert(sizeof(SOP_ColorInfo) == 16, "Incorrect Size"); 1360 | 1361 | static_assert(offsetof(SOP_TextureInfo, numTextures) == 0, "Incorrect Alignment"); 1362 | static_assert(offsetof(SOP_TextureInfo, attribSet) == 4, "Incorrect Alignment"); 1363 | static_assert(offsetof(SOP_TextureInfo, textures) == 8, "Incorrect Alignment"); 1364 | static_assert(offsetof(SOP_TextureInfo, numTextureLayers) == 16, "Incorrect Alignment"); 1365 | static_assert(sizeof(SOP_TextureInfo) == 24, "Incorrect Size"); 1366 | 1367 | static_assert(offsetof(SOP_CustomAttribData, name) == 0, "Incorrect Alignment"); 1368 | static_assert(offsetof(SOP_CustomAttribData, numComponents) == 8, "Incorrect Alignment"); 1369 | static_assert(offsetof(SOP_CustomAttribData, attribType) == 12, "Incorrect Alignment"); 1370 | static_assert(offsetof(SOP_CustomAttribData, floatData) == 16, "Incorrect Alignment"); 1371 | static_assert(offsetof(SOP_CustomAttribData, intData) == 24, "Incorrect Alignment"); 1372 | static_assert(sizeof(SOP_CustomAttribData) == 32, "Incorrect Size"); 1373 | 1374 | static_assert(offsetof(SOP_PrimitiveInfo, numVertices) == 0, "Incorrect Alignment"); 1375 | static_assert(offsetof(SOP_PrimitiveInfo, pointIndices) == 8, "Incorrect Alignment"); 1376 | static_assert(offsetof(SOP_PrimitiveInfo, type) == 16, "Incorrect Alignment"); 1377 | static_assert(offsetof(SOP_PrimitiveInfo, pointIndicesOffset) == 20, "Incorrect Alignment"); 1378 | static_assert(sizeof(SOP_PrimitiveInfo) == 24, "Incorrect Size"); 1379 | 1380 | static_assert(sizeof(OP_SOPInput) == 440, "Incorrect Size"); 1381 | 1382 | static_assert(offsetof(OP_TOPInputDownloadOptions, downloadType) == 0, "Incorrect Alignment"); 1383 | static_assert(offsetof(OP_TOPInputDownloadOptions, verticalFlip) == 4, "Incorrect Alignment"); 1384 | static_assert(offsetof(OP_TOPInputDownloadOptions, cpuMemPixelType) == 8, "Incorrect Alignment"); 1385 | static_assert(sizeof(OP_TOPInputDownloadOptions) == 12, "Incorrect Size"); 1386 | 1387 | static_assert(offsetof(OP_InfoCHOPChan, name) == 0, "Incorrect Alignment"); 1388 | static_assert(offsetof(OP_InfoCHOPChan, value) == 8, "Incorrect Alignment"); 1389 | static_assert(sizeof(OP_InfoCHOPChan) == 56, "Incorrect Size"); 1390 | 1391 | static_assert(offsetof(OP_InfoDATSize, rows) == 0, "Incorrect Alignment"); 1392 | static_assert(offsetof(OP_InfoDATSize, cols) == 4, "Incorrect Alignment"); 1393 | static_assert(offsetof(OP_InfoDATSize, byColumn) == 8, "Incorrect Alignment"); 1394 | static_assert(sizeof(OP_InfoDATSize) == 52, "Incorrect Size"); 1395 | 1396 | static_assert(offsetof(OP_InfoDATEntries, values) == 0, "Incorrect Alignment"); 1397 | static_assert(sizeof(OP_InfoDATEntries) == 48, "Incorrect Size"); 1398 | 1399 | static_assert(offsetof(OP_NumericParameter, name) == 0, "Incorrect Alignment"); 1400 | static_assert(offsetof(OP_NumericParameter, label) == 8, "Incorrect Alignment"); 1401 | static_assert(offsetof(OP_NumericParameter, page) == 16, "Incorrect Alignment"); 1402 | static_assert(offsetof(OP_NumericParameter, defaultValues) == 24, "Incorrect Alignment"); 1403 | static_assert(offsetof(OP_NumericParameter, minValues) == 56, "Incorrect Alignment"); 1404 | static_assert(offsetof(OP_NumericParameter, maxValues) == 88, "Incorrect Alignment"); 1405 | static_assert(offsetof(OP_NumericParameter, clampMins) == 120, "Incorrect Alignment"); 1406 | static_assert(offsetof(OP_NumericParameter, clampMaxes) == 124, "Incorrect Alignment"); 1407 | static_assert(offsetof(OP_NumericParameter, minSliders) == 128, "Incorrect Alignment"); 1408 | static_assert(offsetof(OP_NumericParameter, maxSliders) == 160, "Incorrect Alignment"); 1409 | static_assert(sizeof(OP_NumericParameter) == 272, "Incorrect Size"); 1410 | 1411 | static_assert(offsetof(OP_StringParameter, name) == 0, "Incorrect Alignment"); 1412 | static_assert(offsetof(OP_StringParameter, label) == 8, "Incorrect Alignment"); 1413 | static_assert(offsetof(OP_StringParameter, page) == 16, "Incorrect Alignment"); 1414 | static_assert(offsetof(OP_StringParameter, defaultValue) == 24, "Incorrect Alignment"); 1415 | static_assert(sizeof(OP_StringParameter) == 112, "Incorrect Size"); 1416 | #endif 1417 | --------------------------------------------------------------------------------