Over a million developers have joined DZone.

Chaos in Houdini! Modeling Strange Attractors with Particles

For those of you who are familiar with the Lorenz Attractor (Google ''strange attractors'') this fun dive into rendering chaos will be interesting.

· Mobile Zone

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!

visualization ,3d plotting ,vex

Published at DZone with permission of Simon Gladman, DZone MVB. See the original article here.

Opinions expressed by DZone contributors are their own.

The best of DZone straight to your inbox.

Please provide a valid email address.

Thanks for subscribing!

Awesome! Check your inbox to verify your email so you can start receiving the latest in tech news and resources.

{{ parent.title || parent.header.title}}

{{ parent.tldr }}

{{ parent.urlSource.name }}