Difference between revisions of "OpenFrameworks"

From TouchDesigner Documentation
Jump to: navigation, search
m
m
(Tag: 2018.28070)
 
(3 intermediate revisions by the same user not shown)
Line 44: Line 44:
 
</syntaxhighlight>
 
</syntaxhighlight>
 
and replace them with:
 
and replace them with:
<code>
+
<syntaxhighlight lang=cpp>
    #include "ofMain.h"
+
#include "ofMain.h"
</code>
+
</syntaxhighlight>
  
 
12) In <code>CPlusPlusTOPExample.h</code>, add  
 
12) In <code>CPlusPlusTOPExample.h</code>, add  
<code>
+
<syntaxhighlight lang=cpp>
    #include "ofAppNoWindow.h"
+
#include "ofAppNoWindow.h"
</code>
+
</syntaxhighlight>
 
and add the members  
 
and add the members  
<code>
+
<syntaxhighlight lang=cpp>
    ofAppNoWindow myWindow;
+
ofAppNoWindow myWindow;
    ofGLProgrammableRenderer *renderer;
+
ofGLProgrammableRenderer *renderer;
</code>
+
</syntaxhighlight>
 
to the class body for the TOP.
 
to the class body for the TOP.
  
 
13) In <code>CPlusPlusTOPExample.cpp</code>:
 
13) In <code>CPlusPlusTOPExample.cpp</code>:
 
Add the following lines to the constructor method <code>CPlusPlusTOPExample::CPlusPlusTOPExample</code>:
 
Add the following lines to the constructor method <code>CPlusPlusTOPExample::CPlusPlusTOPExample</code>:
<code>
+
<syntaxhighlight lang=cpp>
    renderer = new ofGLProgrammableRenderer(&myWindow);
+
renderer = new ofGLProgrammableRenderer(&myWindow);
    ofSetDataPathRoot(path_to_dir);
+
ofSetDataPathRoot(path_to_dir);
</code>
+
</syntaxhighlight>
 
Because the application being run is TouchDesigner, openFrameworks will search the installed TouchDesigner's <code>bin</code> for <code>/data</code> by default.
 
Because the application being run is TouchDesigner, openFrameworks will search the installed TouchDesigner's <code>bin</code> for <code>/data</code> by default.
 
If you have any shaders/images to load then <code>ofSetDataPathRootpath_to_dir);</code> is necessary to give openFrameworks the path to the <code>bin/data</code> directory.<br>
 
If you have any shaders/images to load then <code>ofSetDataPathRootpath_to_dir);</code> is necessary to give openFrameworks the path to the <code>bin/data</code> directory.<br>
Line 71: Line 71:
  
 
14) Create a <code>CPlusPlusTOPExample::setup</code> function to be called only once:
 
14) Create a <code>CPlusPlusTOPExample::setup</code> function to be called only once:
  void CPlusPlusTOPExample::setup()  
+
<syntaxhighlight lang=cpp>
  {
+
void CPlusPlusTOPExample::setup()  
 +
{
 
     glewInit();
 
     glewInit();
 
     renderer->setup(3, 2);<br>
 
     renderer->setup(3, 2);<br>
 
     // load any shaders, images, etc
 
     // load any shaders, images, etc
  }
+
}
 +
</syntaxhighlight>
 +
 
 
In addition to <code>glewInit();</code> and <code>renderer->setup(3, 2);</code> this is where you should load any shaders or images.
 
In addition to <code>glewInit();</code> and <code>renderer->setup(3, 2);</code> this is where you should load any shaders or images.
  
Line 88: Line 91:
  
 
17) Enclose the rest of <code>CPlusPlusTOPExample::execute</code> with:<br>
 
17) Enclose the rest of <code>CPlusPlusTOPExample::execute</code> with:<br>
  context->beginGLCommands();<br>
+
<syntaxhighlight lang=cpp>
  // ... rest of your code<br>
+
context->beginGLCommands();<br>
  context->endGLCommands();
+
// ... rest of your code<br>
 +
context->endGLCommands();
 +
</syntaxhighlight>
  
 
18) Add <code>CPlusPlusTOPExample::setup</code> call enclosed by context
 
18) Add <code>CPlusPlusTOPExample::setup</code> call enclosed by context
  
 
19) For any rendering in openFrameworks it's necessary to enclose it with:
 
19) For any rendering in openFrameworks it's necessary to enclose it with:
  renderer->startRender();
+
<syntaxhighlight lang=cpp>
  renderer->setupScreen();<br>
+
renderer->startRender();
  // any binding of shaders/images, drawing, etc.<br>
+
renderer->setupScreen();<br>
  renderer->finishRender();
+
// any binding of shaders/images, drawing, etc.<br>
 +
renderer->finishRender();
 +
</syntaxhighlight>
  
 
Example <code>CPlusPlusTOPExample::execute</code> after steps 15-19
 
Example <code>CPlusPlusTOPExample::execute</code> after steps 15-19
  void CPlusPlusTOPExample::execute(const TOP_OutputFormatSpecs* outputFormat, OP_Inputs* inputs, TOP_Context *context)  
+
<syntaxhighlight lang=cpp>
  {
+
void CPlusPlusTOPExample::execute(const TOP_OutputFormatSpecs* outputFormat, OP_Inputs* inputs, TOP_Context *context)  
 +
{
 
     // query custom parameters <br>
 
     // query custom parameters <br>
 
     int width = outputFormat->width;
 
     int width = outputFormat->width;
Line 117: Line 125:
 
     renderer->finishRender();<br>
 
     renderer->finishRender();<br>
 
     context->endGLCommands();
 
     context->endGLCommands();
  }
+
}
 
+
</syntaxhighlight>
  
 
19) Build the project. All the DLLs required to use the CPlusPlus TOP are in the following directory in the folder where openFrameworks was unzipped:
 
19) Build the project. All the DLLs required to use the CPlusPlus TOP are in the following directory in the folder where openFrameworks was unzipped:
Line 132: Line 140:
 
openFrameworks is open source so you will need to look at the source code to see specifically what functions need to be changed. All drawing, binding, and transforming will need to be changed.<br><br>
 
openFrameworks is open source so you will need to look at the source code to see specifically what functions need to be changed. All drawing, binding, and transforming will need to be changed.<br><br>
 
Example of binding a shader:<br>
 
Example of binding a shader:<br>
  shader.begin();
+
<syntaxhighlight lang=cpp>
 +
shader.begin();
 +
</syntaxhighlight>
 +
 
 
becomes
 
becomes
  renderer->bind(shader);
+
<syntaxhighlight lang=cpp>
 +
renderer->bind(shader);
 +
</syntaxhighlight>
  
 
== Using Input TOPs ==
 
== Using Input TOPs ==
  
 
The following code is an example of how to use input TOPs with openFrameworks:  
 
The following code is an example of how to use input TOPs with openFrameworks:  
<code>
+
<syntaxhighlight lang=cpp>
void
+
void
CPlusPlusTOPExample::execute(const TOP_OutputFormatSpecs* outputFormat,
+
CPlusPlusTOPExample::execute(const TOP_OutputFormatSpecs* outputFormat,
 
  const TOP_InputArrays* arrays,
 
  const TOP_InputArrays* arrays,
 
  void* reserved)
 
  void* reserved)
{
+
{
// ...
+
    // ...
// Use the first input TOP (here we assume it exists but in reality it might not)
+
    // Use the first input TOP (here we assume it exists but in reality it might not)
const TOP_TOPInput *topInput = &arrays->TOPInputs[0];
+
    const TOP_TOPInput *topInput = &arrays->TOPInputs[0];
ofTexture texture;
+
    ofTexture texture;
texture.setUseExternalTextureID(topInput->textureIndex);
+
    texture.setUseExternalTextureID(topInput->textureIndex);
texture.texData.width = topInput->width;
+
    texture.texData.width = topInput->width;
texture.texData.height = topInput->height;
+
    texture.texData.height = topInput->height;
texture.texData.tex_w = topInput->width;
+
    texture.texData.tex_w = topInput->width;
 
 
 
 
texture.texData.tex_h = topInput->height;
+
    texture.texData.tex_h = topInput->height;
texture.texData.textureTarget = topInput->textureType;
+
    texture.texData.textureTarget = topInput->textureType;
// ...
+
    // ...
}
+
}
</code>
+
</syntaxhighlight>
 
[[Category: Touch Glossary‏‎]]
 
[[Category: Touch Glossary‏‎]]

Latest revision as of 04:02, 28 May 2018

TouchDesigner has an infrastructure to process and render openFrameworks projects within the TouchDesigner process via a CPlusPlus TOP.

The TouchDesigner 099 sample project for openFrameworks has been upgraded to the 64-bit openFrameworks v0.9.8, with four examples of a C++ TOP.

Download Examples here:
File:OpenFrameworksExamples.zip

Setup[edit]

1) Download openFrameworks and unzip it to your working directory.

2) Copy the following folder in the TouchDesigner install folder:

   C:/Program Files/Derivative/TouchDesigner099/Samples/CPlusPlus/OpenGLTOP

to the following directory in the unzipped openFrameworks folder:

   apps/myApps

Rename the folder to your project's name.

Note: This is not strictly necessary, but it makes it a lot easier because openFrameworks includes a property sheet that lists all the "Additional Include Directories" relative to the root of the openFrameworks folder. Otherwise all the include directories would have to be added manually.

3) Open the Visual Studio Solution (.sln) from the folder you just copied over. You must use Visual Studio 2012 or higher to be able to compile openFrameworks.

4) In Visual Studio, right click on the solution in the "Solution Explorer" and click "Add > Existing Project".

5) Locate the folder where openFrameworks was unzipped and select:

   libs/openFrameworksCompiled/project/vs/openframeworksLib.vcproj

6) Right click on the CPlusPlusTOPExample project and click "Project Dependencies". Check the box next to openframeworksLib in the Dependencies page. Click OK.

7) Right click on the CPlusPlusTOPExample project and click References. Click "Add New Reference" and check the box next to openframeworksLib. Click OK.

8) Right click on the CPlusPlusTOPExample project and click Properties. Find "Configuration Properties > General" and set "Output Directory" to $(SolutionDir)\bin

9) Click "View > Property Manager" (or "View > Other Windows > Property Manager"). Expand the CPlusPlus TOP project. For each of the debug folders, right click and click "Add Existing Property Sheet". Locate the folder where openFrameworks was unzipped and select:

   libs/openFrameworksCompiled/project/vs/openFrameworksDebug.props

10) Do the same for the release folders, except instead select:

   libs/openFrameworksCompiled/project/vs/openFrameworksRelease.props

11) Go back to the "Solution Explorer" and open TOP_CPlusPlusBase.h. Remove the following lines:

#include <windows.h>
#include <cstdio>

and replace them with:

#include "ofMain.h"

12) In CPlusPlusTOPExample.h, add

#include "ofAppNoWindow.h"

and add the members

ofAppNoWindow myWindow;
ofGLProgrammableRenderer *renderer;

to the class body for the TOP.

13) In CPlusPlusTOPExample.cpp: Add the following lines to the constructor method CPlusPlusTOPExample::CPlusPlusTOPExample:

renderer = new ofGLProgrammableRenderer(&myWindow);
ofSetDataPathRoot(path_to_dir);

Because the application being run is TouchDesigner, openFrameworks will search the installed TouchDesigner's bin for /data by default. If you have any shaders/images to load then ofSetDataPathRootpath_to_dir); is necessary to give openFrameworks the path to the bin/data directory.
Note: path_to_dir must use forward slashes, and it can either be an absolute path, or a relative path from TouchDesigner's executable.
Example: ofSetDataPathRoot("../../../../of_v0.9.3_vs_release/apps/myApps/CPlusPlusTOPExample/bin/data/")

14) Create a CPlusPlusTOPExample::setup function to be called only once:

void CPlusPlusTOPExample::setup() 
{
    glewInit();
    renderer->setup(3, 2);<br>
    // load any shaders, images, etc
}

In addition to glewInit(); and renderer->setup(3, 2); this is where you should load any shaders or images.

15) At the top of CPlusPlusTOPExample::execute query any custom parameters.

16) Query for the resolution width and height:

 int width = outputFormat->width;
 int height = outputFormat->height;

Then setup the window with the width and height of the C++TOP:

 ofSetupOpenGL(&myWindow, width, height, OF_WINDOW);

17) Enclose the rest of CPlusPlusTOPExample::execute with:

context->beginGLCommands();<br>
// ... rest of your code<br>
context->endGLCommands();

18) Add CPlusPlusTOPExample::setup call enclosed by context

19) For any rendering in openFrameworks it's necessary to enclose it with:

renderer->startRender();
renderer->setupScreen();<br>
// any binding of shaders/images, drawing, etc.<br>
renderer->finishRender();

Example CPlusPlusTOPExample::execute after steps 15-19

void CPlusPlusTOPExample::execute(const TOP_OutputFormatSpecs* outputFormat, OP_Inputs* inputs, TOP_Context *context) 
{
    // query custom parameters <br>
    int width = outputFormat->width;
    int height = outputFormat->height;<br>
    ofSetupOpenGL(&myWindow, width, height, OF_WINDOW);<br>
    context->beginGLCommands();<br>
    if(!isSetup)
    {
      setup();
    }<br>
    renderer->startRender();
    renderer->setupScreen();<br>
    // any binding of shaders/images, drawing, etc.<br>
    renderer->finishRender();<br>
    context->endGLCommands();
}

19) Build the project. All the DLLs required to use the CPlusPlus TOP are in the following directory in the folder where openFrameworks was unzipped:

   apps/myApps/<project-name>/bin

It is important that all the DLLs remain together in the same directory because of dependencies. TouchDesigner will automatically load the other required DLLs if they are in the same directory.

Translating openFrameworks code to work within TouchDesigner[edit]

The creation of an ofAppNoWindow using the above steps will cause many openFrameworks functions to break down and ofGetCurrentRenderer(), which queries the renderer of the window, is to blame for this.
The renderer holds much of the useful renderering functionality, however ofAppNoWindow has an ofNoopRenderer which is missing crucial functionality. As a result ofGetCurrentRenderer() returns an unusable renderer that will either lead to a crash or do nothing.
In order to render in TouchDesigner using openFrameworks ofGetCurrentRenderer() must be bypassed, meaning any function that calls ofGetCurrentRenderer() cannot be used. This is exactly why an ofGLProgrammableRenderer object is created in steps 12-13.
To translate any openFrameworks function that calls ofGetCurrentRenderer(), look at the source and see how it uses the renderer, then move that functionality to your CPlusPlusTOPExample using the created ofGLProgrammableRenderer object.
openFrameworks is open source so you will need to look at the source code to see specifically what functions need to be changed. All drawing, binding, and transforming will need to be changed.

Example of binding a shader:

shader.begin();

becomes

renderer->bind(shader);

Using Input TOPs[edit]

The following code is an example of how to use input TOPs with openFrameworks:

void
CPlusPlusTOPExample::execute(const TOP_OutputFormatSpecs* outputFormat,
 				const TOP_InputArrays* arrays,
 				void* reserved)
{
    // ...
    // Use the first input TOP (here we assume it exists but in reality it might not)
    const TOP_TOPInput *topInput = &arrays->TOPInputs[0];
    ofTexture texture;
    texture.setUseExternalTextureID(topInput->textureIndex);
    texture.texData.width = topInput->width;
    texture.texData.height = topInput->height;
    texture.texData.tex_w = topInput->width;
 	
    texture.texData.tex_h = topInput->height;
    texture.texData.textureTarget = topInput->textureType;
    // ...
}

An Operator Family that creates, composites and modifies images, and reads/writes images and movies to/from files and the network. TOPs run on the graphics card's GPU.

A Link.

Any of the procedural data operators. OPs do all the work in TouchDesigner. They "cook" and output data to other OPs, which ultimately result in new images, data and audio being generated. See Node.