Close
Tutorial

WaveField TOX - POPs without the hassle For Beginners & Intermediate

A drop-in TouchDesigner component for building wavefield visualisations from a library of seventeen wave equations across twelve source shapes and six instancing modes. It is audio reactive, LiDAR ready, and entirely driven by custom parameters on the TOX itself.

What it does

The Wavefield Grid TOX takes a point cloud and runs every point through a GLSL compute shader that displaces it according to a chosen wave equation. The point cloud can be one of the built in shapes, a custom POP you wire in yourself, or a live point cloud from a LiDAR scanner. After the displacement step, the TOX can optionally copy a small primitive such as a cube, sphere, tetrahedron, or line onto every displaced point, turning a flat grid into a voxelised wavefield.

The output is a standard POP stream. You wire it into a Geometry COMP and render it the same way you would render any other POP chain in TouchDesigner.

Installation

Drop the saved TOX file onto any network. If you have been working inside the demo project, it lives at slash project1 slash wavefield grid. The TOX has four input connectors on its left side and one output connector on the right. Wire the output to a Geometry COMP that contains an In POP feeding an Out POP. Render the Geometry COMP with a Camera COMP, a Light COMP, and a PBR material through a Render TOP. The demo project ships with that whole rendering chain already wired in alongside the TOX, so you can use it as a reference if you prefer.

The four inputs

When you hover over any of the four input connectors on the TOX in the network editor, you will see a label appear that tells you what that input expects.

The first input is a CHOP input. This is for any CHOP data you want to drive the Audio Waveform equation. It accepts an audio file, an audio device, an audio spectrum CHOP, an LFO, anything. The data is sampled across the X axis of your wavefield, so a CHOP with many samples gives you finer detail across the grid.

The second input is a POP input for a custom source shape. Anything you can build as a POP chain can be used as the source point cloud that the wave equation operates on. To use it, select Custom POP from the Source Shape menu on the TOX.

The third input is a POP input for a custom instance shape. This is the small primitive that gets copied onto each displaced point when you have the Instance Shape menu set to Custom POP. Keep the geometry small, ideally under a couple hundred vertices, because every point of your source cloud gets a copy.

The fourth input is a POP input intended for an external point cloud, most often a LiDAR scanner running through TDLidar, or a Kinect, RealSense, or Zed depth camera. Whatever you put on this connector becomes available as External Cloud slash TDLidar in the Source Shape menu.

All four inputs are optional. If you do not connect them and you do not select the menu options that route to them, nothing breaks.

Custom parameters

The TOX has four parameter pages: Shape, Wave, Modes, and Color.

Shape page

Source Shape is the point cloud that gets fed into the wave equation. There are twelve options including the two custom inputs. The built in options cover a flat grid as triangles, points, or a wireframe, a sphere, a torus, a tube, a spherical point cloud, a line, a circle, and a 3D volumetric grid.

Instance Shape controls what gets drawn at each displaced point. Raw skips copying entirely and just draws the wavefield itself, which is the right choice when your source shape already has its own geometry. The other options copy a small cube, sphere, tetrahedron, line, or your own custom geometry onto every displaced point.

Wave page

Wave Equation picks one of seventeen equations, listed in detail in the next section.

Displacement Axis controls which direction the wave pushes points. You can choose the X, Y, or Z world axes, a radial direction outward from the origin, or a custom direction defined by the Direction X, Y, and Z parameters lower on the page. Y axis is the default and works for the flat grid layouts.

Amplitude, Frequency, Speed, Phase, and Decay are the universal wave knobs. Amplitude scales the height of the wave. Frequency is the spatial frequency, basically how tightly packed the wave is across the grid. Speed controls how fast the wave moves. Phase shifts the wave in time. Decay only affects the damped ripple equation, controlling how quickly waves fade with distance from the centre.

Direction X, Y, and Z define a unit vector used by the directional plane wave, the Gerstner ocean equation, and the custom direction axis option.

Modes page

Source 1 and Source 2 set the positions of the two point sources used by the Interference equation. With them at minus two zero zero and two zero zero you get the classic two slit interference pattern.

Gaussian Sigma is the width of the wavepacket used by the Gaussian Wavepacket equation. Smaller values make a tighter, more localised pulse.

Chladni Mode m and Chladni Mode n are integer mode numbers for the Chladni Pattern equation. Different integer combinations give wildly different sand pattern geometries, just like a real Chladni plate experiment.

Color page

Color Mix and the Color Low and Color High swatches are reserved for a future shader pass that writes per point colour. In the current build, colour comes from the PBR material assigned to your Geometry COMP. Edit the base colour of the material to recolour the wavefield.

The seventeen wave equations

Equation zero is a Sine Plane Wave travelling along the X axis. It is the simplest wave, a sine that propagates across the grid in one direction.

Equation one is a Sine Plane Wave travelling along the Z axis. Same shape as zero, rotated ninety degrees.

Equation two is a Sine Plane Wave that travels in whatever direction you set with the Direction X, Y, and Z parameters. Use this to make diagonals or arbitrary heading waves.

Equation three is a Radial Ripple. It emanates from the origin like a stone dropped in still water. Concentric rings travel outward.

Equation four is a Damped Ripple. Same idea as Radial Ripple but the amplitude fades exponentially with distance, so waves are tall near the origin and almost flat at the edges. The Decay parameter controls how aggressive the falloff is.

Equation five is a Standing Wave in one dimension. The wave does not travel, it stays put and pulses in place. This is what you get when two travelling waves moving in opposite directions interfere.

Equation six is a Standing Wave in two dimensions, the product of a sine in X and a sine in Z, pulsing in time. You get a checkerboard pattern of peaks and troughs that flip polarity together.

Equation seven is a Chladni Pattern, modelling the standing wave nodes on a vibrating square plate. The Chladni Mode m and Chladni Mode n parameters on the Modes page choose which vibration mode you are seeing. Try three and two, then five and three, then six and one, to feel the variety.

Equation eight is a Cross Wave, the sum of two perpendicular travelling sine waves. It looks like a wavefield with diagonal travelling crests, the kind of thing you see on the surface of a swimming pool with two wave sources.

Equation nine is Interference between two point sources, the two slit experiment. You will see hyperbolic interference fringes between the sources. Move Source 1 and Source 2 on the Modes page to change the geometry.

Equation ten is a Gaussian Wavepacket, the localised packet from quantum mechanics. It travels across the grid with a Gaussian envelope filled with a cosine carrier wave, just like a free particle wavefunction. The Sigma parameter sets how localised the packet is. The packet wraps around when it reaches the edge of the grid, so it loops forever.

Equation eleven is a KdV Soliton, the solitary wave first observed by John Scott Russell on the Edinburgh canal in 1834. A single tall sech squared pulse that maintains its shape as it travels. Like the wavepacket, it wraps around the grid so the soliton loops forever.

Equation twelve is a Beat Pattern, the product of two sine waves at slightly different frequencies. You will see a slow pulsing envelope on top of fast oscillation, which is the same effect you hear when two musical notes are nearly in tune.

Equation thirteen is a Gerstner Ocean wave. This one is special because it displaces points in X, Y, and Z together rather than just along the displacement axis. It produces realistic ocean swells with the sharp peaks and rounded troughs that real water has. The direction the swell travels is set by the Direction parameters.

Equation fourteen is a Bessel Radial wave, similar in spirit to the radial ripple but with a slower envelope decay that mimics a Bessel function of the first kind, the kind of pattern you see in real circular membrane vibrations.

Equation fifteen is a Turbulent wave, a sine combined with simplex noise that varies in space and time. It hides the regular sine structure under organic flowing noise, which is the right choice when you want something that does not look obviously mathematical.

Equation sixteen is the Audio Waveform. Whatever CHOP you have connected to the first input on the TOX gets sampled across the X axis of your wavefield, with the sample value used as the displacement amount. This is the audio reactive equation, covered in detail below.

Audio reactive setup

To make the wavefield react to audio, you need three things wired together.

Start with an audio source. For pre recorded music drop an Audio File In CHOP and load a file. For live microphone or audio interface input use an Audio Device In CHOP and pick the device on its parameter page. For frequency band reactivity drop an Audio Spectrum CHOP after either of those.

Wire the audio CHOP to the first input connector on the Wavefield Grid TOX, the topmost connector on its left side. That is the CHOP input.

On the TOX parameters, open the Wave page and change Wave Equation to option sixteen, the Audio Waveform. Now increase Amplitude until you see motion in the wavefield. The displacement at each grid point is the audio sample value multiplied by Amplitude, so a quiet signal needs more amplitude to be visible.

A practical tip. Audio CHOPs run at audio rate, often forty four thousand one hundred samples per second, and you do not need that resolution to draw a wavefield. Drop a Resample CHOP between the audio source and the TOX, set its sample rate down to a few hundred samples, and you will get a smoother wavefield with much lower GPU cost. If you swap the audio source for an Audio Spectrum CHOP, the X axis of your wavefield becomes a frequency axis instead of a waveform, which gives you a classic bar visualiser look across the surface.

Using a live point cloud from TDLidar

This is where the TOX really earns its keep for installation and live performance work. The goal is to take a live point cloud from a LiDAR scanner and make it the source point cloud that the wave equations operate on.

You need a LiDAR device, ideally one that streams point data via OSC. TDLidar is a popular tool for this on TouchDesigner. Alternatively you can use a Kinect Azure, an Intel RealSense, a Stereolabs Zed, or any other depth camera that can produce a point cloud in TouchDesigner.

The pipeline for live OSC LiDAR works as follows. Your LiDAR device or TDLidar app sends out OSC packets over UDP containing position data for each point. Inside TouchDesigner you drop an OSC In CHOP and set its network port to whatever the sender is using. The TDLidar default is port seven thousand. Then you configure the OSC In CHOP to parse the incoming address pattern so that the point positions arrive as proper channels, typically named tx, ty, and tz.

Next you drop a CHOP to POP operator and wire the OSC In CHOP into it. On the CHOP to POP, point its CHOP parameter at the OSC In CHOP, set the channel match to the names of your position channels, set the output to point primitives, and enable the option to use P from the CHOP channels so that the data becomes actual point positions rather than just attributes.

Wire the output of the CHOP to POP through a Null POP for cleanliness, then wire the Null POP into the fourth input on the Wavefield Grid TOX. The fourth input is the one labelled External Point Cloud when you hover it. Finally, on the TOX parameters, open the Shape page and change Source Shape to External Cloud slash TDLidar. The LiDAR scan is now the source point cloud, and every wave equation runs on it.

For Kinect Azure the pipeline is simpler because the depth data arrives as a TOP texture. Use a Kinect Azure TOP, then a Kinect Azure Select TOP set to depth XYZ, then a TOP to POP. The TOP to POP treats each pixel as a point with its position read from the RGB channels of the texture. Wire it into the fourth input on the TOX.

For pre recorded point clouds, use a Point File In TOP to load a ply or obj file, then a TOP to POP to convert it, then into the fourth input. This is useful for testing the LiDAR mode without a device connected.

Some tips for working with LiDAR data. Most LiDAR streams produce between fifty thousand and a quarter million points per frame, which is a lot for the GPU to instance cubes onto. Before the TOX, use a Random POP or a Select POP to subsample the cloud down to twenty or thirty thousand points. You will lose almost no visual structure and the frame rate will be far happier. The Radial From Origin displacement axis tends to look best with LiDAR data, because points push outward from the scanner position and the whole cloud appears to breathe. The Turbulent equation is also a favourite, because the simplex noise hides any visible scan lines from the LiDAR. Switching the Instance Shape to Cubes while LiDAR is the source converts every LiDAR point into a small wave displaced cube, which produces an instant voxelised cloud effect.

Custom source and instance shapes

You do not have to live with the built in primitives. Build any POP chain in TouchDesigner, anything from a text outline to a loaded mesh to your own procedural pyramid, and wire its output into the second input on the TOX. Then select Custom POP from the Source Shape menu. The wave equations now operate on your custom geometry.

The same applies for the instance shape. Build a small POP, ideally under a couple hundred vertices because every wave point gets a full copy, and wire it into the third input on the TOX. Select Custom POP from the Instance Shape menu. Now every wave displaced point becomes a copy of your custom geometry.

You can combine both. Use a custom logo as the source and a custom snowflake as the instance, animated by Chladni mode five and three. The whole network becomes parameter driven content with you in full control.

Performance tips

The biggest lever you have is the resolution of the source shape. The built in flat grid sources default to between sixty by sixty and eighty by eighty points. Halving the rows and columns gives you a four times speedup. For most projection mapping and visualiser work, forty by forty is plenty.

The second biggest lever is whether you are instancing or not. Instance Shape set to Raw skips the entire copy stage. This is the right mode when your source shape already has the geometry you want, like the sphere or torus, or when your source cloud is very large.

For custom instance shapes, keep the unit geometry tiny. The total number of vertices that the GPU has to draw is the number of template points multiplied by the vertex count of the instance shape. A sixty by sixty grid copied with a two hundred vertex sphere is over seven hundred thousand vertices.

For LiDAR work, subsample upstream of the TOX. A Random POP filtered to every fifth point can take a quarter million cloud down to fifty thousand without losing visible structure.

Quick recipes

For the iconic voxel ripples look that you see in TouchDesigner promotional material, set Source Shape to Flat Grid Points, Instance Shape to Cubes, Wave Equation to Radial Ripple, Amplitude around zero point six, and Frequency around two.

For an ocean swell, set Source Shape to Flat Grid Mesh, Instance Shape to Raw, Wave Equation to Gerstner Ocean, Amplitude one, Frequency zero point eight, Speed two point five, and Direction X to one with Direction Z to zero point three for a diagonal swell.

For Chladni sand patterns, set Source Shape to Flat Grid Points, Instance Shape to Spheres, Wave Equation to Chladni Pattern, and try Chladni Mode m at five and Chladni Mode n at three on the Modes page.

For a solitary pulse traveling across the grid, set Source Shape to Flat Grid Mesh, Instance Shape to Raw, Wave Equation to KdV Soliton, Amplitude two, Frequency one point five, Speed one point five. You will see a single tall pulse loop across the grid.

For a pulsing sphere, set Source Shape to Sphere, Instance Shape to Raw, Wave Equation to Damped Ripple, and change Displacement Axis to Radial From Origin. The sphere surface will pulse in and out radially.

For audio reactive bars, set Source Shape to Flat Grid Lines, Instance Shape to Raw, Wave Equation to Audio Waveform, and wire an Audio Spectrum CHOP into the first input.

For a live LiDAR cloud with organic motion, set Source Shape to External Cloud slash TDLidar, Instance Shape to Tetrahedra, Wave Equation to Turbulent, low Amplitude around zero point three, and low Frequency.

Troubleshooting

If your render comes out black, the most common culprit is the camera. Open the Camera COMP and set its Look At parameter to point at your Geometry COMP path. Bump the light dimmer to two or higher and make sure the material base colour is bright enough to be visible.

If you get a compile error on the wavefield GLSL POP, open the docked text DAT named wavefield compute. The error message includes line numbers. Do not redeclare any sampler uniforms manually in the shader, because TouchDesigner auto injects them from the sampler parameter slots on the GLSL POP.

If the Gaussian Wavepacket or KdV Soliton equations look invisible, lower the Frequency, because at high frequency the pulse becomes a single tall narrow spike that is hard to see. Increase the Amplitude. The default Speed of one to three gives one full traverse of the grid every few seconds.

If the Audio Waveform equation does not produce any motion, check that your CHOP is actually connected to the first input and is producing samples. Add a Null CHOP between your source and the TOX, click on it, and confirm in the viewer that you can see channel data flowing.

If your LiDAR cloud appears as a single dot at the origin, your CHOP to POP is not mapping the channels to point positions. Open it and check that Channel Match contains the exact channel names that your OSC stream is producing, that Output is set to point primitives, and that the Use P from CHOP toggle is enabled.This TOX uses built in Touchdesigner components and is Mac & Windows Compatible

Experience level 

Comments