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!