This provides a basic, canonical template for making geometry / mesh objects with Avendish: a single C++ object that generates a mesh and is compiled, without rewrite, to several host plug-in formats.
It is the geometry counterpart of the audio processor template: where that one ticks per audio buffer and processes samples, this one ticks per frame and produces a mesh (vertices, normals, colors, indices) on its output.
The avnd_make_geometry(...) macro in CMakeLists.txt instantiates the geometry
back-ends. From src/Model.hpp you get:
| Back-end | Object kind | SDK required |
|---|---|---|
| TouchDesigner SOP | Surface Operator | TouchDesigner Custom Operator SDK |
| TouchDesigner POP | Particle Operator | TouchDesigner Custom Operator SDK |
| Godot | GDExtension node producing an ArrayMesh |
none — godot-cpp is fetched automatically |
| ossia score | geometry process | libossia |
Back-ends whose SDK is not provided are silently skipped, so you can build just the ones you need.
Note on Max/MSP: Max is intentionally not a geometry target. Max's Avendish binding (Jitter) only handles matrix / texture outputs and rejects geometry output ports at compile time, so a geometry object cannot be emitted for Max. Use the audio/message template for Max objects.
src/Model.hpp / src/Model.cpp implement MyGeometry, a generator that emits a
subdivided plane mesh displaced by a sine wave, with controllable size, subdivision
count, displacement height and color. It writes positions, normals, per-vertex colors
and a triangle index buffer into a
halp::position_normals_color_index_geometry
output.
Start from there: change the ports in the inputs struct, and rewrite operator() to
fill the mesh buffers however you like. See
examples/Tutorial/CubeGenerator.hpp
in Avendish for the canonical reference, and halp/geometry.hpp for the other ready-made
mesh layouts (position-only point clouds, packed/interleaved attributes, per-attribute
buffers, fully dynamic run-time geometry, …).
cmake -S . -B build -G Ninja \
-DCMAKE_BUILD_TYPE=Release
cmake --build buildWith no extra options this builds the Godot back-end (it fetches godot-cpp
automatically). To enable the other back-ends, pass the relevant SDK paths below.
To see a complete build procedure, refer to the Github actions workflows, which compile the project on clean virtual machines.
godot-cpp is fetched via CMake FetchContent by default. To build against an existing
checkout instead, pass:
-DGODOT_CPP_PATH=path/to/godot-cppThe build produces build/godot/my_geometry_geo.{so,dll,dylib} and a matching
.gdextension file you can drop into a Godot project.
Point CMake at a TouchDesigner Custom Operator SDK whose include/ directory contains
the operator base headers. Avendish reads ${TOUCHDESIGNER_SDK_PATH}/include/:
-DTOUCHDESIGNER_SDK_PATH=path/to/CustomOperatorSamplesThis produces a TouchDesigner SOP (build/td/...SOP...) and a TouchDesigner
POP (build/td/...POP...).
- The SOP back-end only needs
CPlusPlus_Common.h+SOP_CPlusPlusBase.h, present in the publicTouchDesigner/CustomOperatorSamples. - The POP back-end is experimental and additionally needs
POP_CPlusPlusBase.hplus the POP-enabledCPlusPlus_Common.h, which Derivative ships only inside the experimental TouchDesigner installation (Samples/CPlusPlus). Thejcelerier/CustomOperatorSamplesfork bundles these underinclude/, so pointingTOUCHDESIGNER_SDK_PATHat a checkout of that fork builds both SOP and POP. This is what the CI does.
Note: TouchDesigner uses the MSVC ABI on Windows — build with clang-cl or MSVC, not MinGW (the CI builds the TouchDesigner back-ends on Linux and macOS with Clang).
Install libossia (or build score and point CMake at
its 3rdparty tree) so that find_package(ossia) succeeds; the geometry process then
becomes available inside ossia score.
- Support importing the template with a package manager
- Max/MSP (Jitter) mesh output