I recently posted Chaos in Swift! Visualizing the Lorenz Attractor with Metal, which was inspired by a Houdini tweet from Erwin Santacruz. It appears that Erwin's solution creates geometry, so I thought I'd look at this from a different perspective to see if I could create a particle based visualization of strange attractors in Houdini.
So, it turns out to be a lot simpler than I expected!
The secret sauce is the POP Wrangle node. This node runs a VEX expression against every particle and allows Houdini control over each particle's properties such as size, position, and velocity. The number of solves per-frame is controlled by the POP Solver's subsets attributes.
To give my attractors some variance, my projects use very small spheres as the particle source. Once Houdini had created a DOP Network, I've removed gravity, added the POP Wrangle and an instance geometry node for fine control over particle size:
The VEX inside the POP Wrangle nodes isn't a million miles away from my Metal code. The main difference is that for each invocation, it's getting and setting the x, y and z attributes of each particle's position (@P). So, the Hadley attractor POP Wrangle expression is:
float alpha = 0.2;
float beta = 4.0;
float zeta = 8;
float d = 1.0;
float deltaX = -@P.y * @P.y - @P.z * @P.z - alpha * @P.x + alpha * zeta;
float deltaY = @P.x * @P.y - beta * @P.x * @P.z - @P.y * d;
float deltaZ = beta * @P.x * @P.y + @P.x * @P.z - @P.z;
@P.x += deltaX / 300.0;
@P.y += deltaY / 300.0;
@P.z += deltaZ / 300.0;
...and the Lorenz Mod 2 attractor POP Wrangle expression is:
float a = 0.9;
float b = 5;
float c = 9.9;
float d = 1;
float deltaX = -a * @P.x + @P.y * @P.y - @P.z * @P.z + a * c;
float deltaY = @P.x * (@P.y - b * @P.z) + d;
float deltaZ = -@P.z + @P.x * (b * @P.y + @P.z);
@P.x += deltaX / 1000.0;
@P.y += deltaY / 1000.0;
@P.z += deltaZ / 1000.0;The final renders have some depth-of-field and motion-blur added with some nausea inducing camera moves (I'm no cinematographer!). Enjoy!