We all love natural and realistic motion of fluid simulation. I often find particle simulation driven by fluid simulation is very useful. There are few benefits.
First, I can make much finer detail using particles than just using fluid voxel as volume. I don’t need too high grid resolution either, which makes me able to iterate more.
The other reason, which I’m going to talk about here, is that I can deform the particles using particle expression with all useful particle attributes after the fluid simulation is done.
This is a typical example of particle simulation driven by fluid velocity field. This type of effect can be achieved in many different ways in almost all software packages in these days. I’m using Maya fluid effects and particle expression here, but I’m sure it can be done in other applications too.
By simply using two particle systems, we can deform particle’s motion. This example is bending particle position using rot() in Maya particle expression.
Here, I’m normalizing particle positions, which means I’m projecting fluid-like motion onto a sphere. I can also twist them by rotating the particle positions based on translate Y.
vector $newPosition = particle_originalShape.position; // normalize float $radius = 5; vector $normalizedPosition = unit($newPosition) * $radius; // twist $newPosition = rot($newPosition, <<0,1,0>>, $newPosition.y * ctrl.twist * 10); // offset $newPosition += <<-14, 0, 0>>; // apply new position particle_deformedShape.position = $newPosition;
Here are a cylinder and a cone.
vector $originalPosition = particle_originalShape.position; vector $newPosition = $originalPosition; // twist $newPosition = rot($newPosition, <<0,1,0>>, ($newPosition.y - 4) * ctrl.twist * 0.5); // make sphere float $radius = 4.5; vector $sphereP = unit($newPosition ) * $radius; // make cylinder vector $ring = <<$newPosition.x, 0, $newPosition.z>>; vector $normRing = unit($ring) * $radius; vector $cylinderP = <<$normRing.x, $newPosition.y, $normRing.z>>; $newPosition = $cylinderP; // make cone float $distFromAxis = sqrt(mag(<<$cylinderP.x, 0, $cylinderP.z>>)) * 0.5; $distFromAxis *= 1 - (linstep(-5.4, 5.8, $cylinderP.y) * ctrl.coneDistance); vector $coneP = <<$cylinderP.x * $distFromAxis, $cylinderP.y, $cylinderP.z * $distFromAxis>>; $newPosition = $coneP; // blend $newPosition = $originalPosition + (($newPosition - $originalPosition) * ctrl.unitDistance); // offset $newPosition += <<-14, 0, 0>>; // apply new position particle_deformedShape.position = $newPosition;
This is using a nurbs surface. I’m using goalU for positionX goalV for positionY, and goaloffset for positionZ.