Remember 3December
Find out where to celebrate your 3D CG art...
Theme color:
  • 1/3
You are here: Homepage /  Blogs /  Duncan's Blog / Pouring Water with nParticles
Pouring Water with nParticles
Posted: Oct 29, 2008
Category: nParticles
Social Media:
Bookmark and Share
With the introduction of nParticles in Maya 2009 one now has a tool that can handle pouring liquids. (note that Maya Fluids, despite its name, is currently better suited for gaseous effects than pouring water) If one toggles on "Enable Liquid Simulation" on the particle system a "Smooth Particle Hydrodynamics" (SPH) solver is used. Note that in general one should turn OFF self collision when using this. Self collisions, even with friction set to zero, will tend to lock up the flow as well as prevent particles from settling into a smooth surface. By contrast the SPH solver does not compute collisions but rather repels and attracts adjacent particles based on the cumulative overlap, or density. The target density or cumulative overlap of the particles is controlled by the attribute "Rest Density". The default value of 2.0 corresponds to two particles totally overlapping, however note that if we add a third particle then they will not totally overlap because that would make the cumulative density 3.0. The attribute "liquidRadiusScale" is simply a multiplier of the radius of the particle when determining the SPH overlap, or density. It helps to make this less than one when using the blobby surface rendering so that the particles overlap enough to create a smooth surface.
The smooth surface we render is called an isosurface. An isosurface is the boundary where the cumulative particle density is equal to the value set by the "threshold" attribute. Each particle has a density that is 1.0 at the particle center going to zero at its boundary. At a value of zero the surface is at the particle boundary, and as one increases the threshold to 1.0 the surface will move inwards towards the center of the particle. Higher thresholds make the resulting surface smoother. At a threshold of 1.0 or greater individual particles will only appear when they overlap others.
In Maya there are two primary methods to render this particle isosurface. We can directly raytrace the isosurface by setting the particle RenderType to "Blobby Surface". Or in Maya 2009 we now have the option to create a polygon mesh of the isosurface. To do this one calls "Convert: nParticle to Polygons", which essentially makes the particle system upstream construction history for a mesh node. Each method has its advantages and disadvantages. The polygon mesh method can result in a very large number of triangles, which can overflow available memory as well as take a long time to generate. The direct blobby raytrace method does not use much memory but can be very slow to raytrace, particularly with refractions through dense overlapping particles (opaque milk is generally faster than water). The blobby raytrace is generally superior if you have lots of fine droplets, as oppose to a smooth contained fluid. Also in Maya2009 motion blur on the particle mesh will not work properly and should be disabled, while one can use Motion blur in Mental Ray when using the direct blobby raytrace. As well if one wished to have different transparency and color values on a per particle basis it will work OK with the direct blobby raytrace but not with the mesh method. One advantage of the mesh method is that one can refine and smooth the resulting surface. The smoothing available this way is of a higher order than the smoothing that occurs by simply increasing the particle size and blobby threshold. In this tutorial both methods of rendering are explored.

INITIAL SETUP

 
To start with we will create two containers to pour with.
1. Create the cup. Create a default poly cylinder, setting the subdivisions Caps to zero and the height to 2.5. Then select the top face of the cylinder and delete to create a cup. Use "Edit Mesh:extrude" to thicken the cup. The position the cup up and to the side where we will pour it from (translate = -0.7, 6.2, 0.1).
2. Create the glass. It helps if the glass to pour into has a rounded bottom so that the water can slosh around better. Create a nurbsCurve for the cup profile and use "Surfaces: Revolve" to create the glass shape, setting "Output Geometry" to Polygons in the revolve options. In order to get a good fit of the polygons edit the resulting "nurbsTessellate1" node, using "enable advanced tessellation" and setting the general tessellation options. Optionally one and use "Normal: set Normal Angle" and adjust the angle such that the body of the glass will render smooth, but the lip have a sharp edge, like crystal.
3. Fill the cup. First do "nParticles:Create nParticles: Water" to set the style to water. Now select the cup and bring up the option box for "Create nParticles: Fill Object". Set the resolution to 30 and make the MaxY 0.4 ( just under half full ). Also toggle on "Double Walled" (so that particles are not created inside the wall of the cup) then click the "Particle Fill" button on the option box.
Note that with this workflow the total particle count is fixed and difficult to change later. Instead one could use a cylinder shaped volume particle emitter, emit some particles, set initial state and toggle off emission. This would allow for later changing the particle count by clearing initial state and re-emitting. Currently one can't use the fill command to add into an existing particle system. Emitted particles are more random than the fill method, however one can run the simulation to settle their positions.

SIMULATION

 
1. Select the cup and glass then do "nMesh:Create Passive Collider"
2. Playback to view simulation. Note that the particles collapse to the cup bottom as if they are not colliding. This is because the fill command initially sets the particle radius such that they just touch, while the particle liquid simulation treats the radius as a max interaction distance not a collide distance. Additionally the default simulation is quite compressible, so a large stack of particles will tend to compress like a weak spring under gravity.
3. Adjust the particle radius values: First off we want some overlap where the particles collide with surfaces so they look more like drops as oppose to spheres, so make the collideWidthScale 0.5(note that this will cause the particles to compress even more). We also want even more self overlap of the particles so that blobby rendering will look smooth(rather than lumpy), so set the "Liquid Radius Scale" to 0.65(note this is very similar to "Self Collide Width Scale"). Next set the nucleus substeps to 20, which will make the water much less compressible and improve the collision quality( although it will slow down the simulation ). Now increase the particle radius just to the point where the particles will settle near the starting point(in this case around 0.13). Playback until it settles then select the particle system and do "nSolver: Initial State: Set From Current". When you rewind and playback it should now remain stationary. Note that you may also wish to randomize the radius values a little to help prevent stacking along boundaries. This can be done by setting the "Radius Scale Input" to RandomizedID and then increasing the "Radius Scale Randomize" to something like 0.1. Note that you may need to slightly increase the overall radius when doing this. Something else that can help is to keyframe the particle "Damp" such that it is initially 1 or so then goes to zero over after a couple of frames. This allows one to vary attributes that affect the initial state without always needing to reset the initial state to keep particles from exploding apart.
4. Keyframe the cup rotating to pour the fluid into the glass: Select Cup, hit "s" key to keyframe. Go to frame 30 rotate the cup (something like 0,0,-110) and hit "s" again.
5. On the nucleus node turn on "Use Plane" so that the particle system will collide with the ground. We can also at this point create a ground plane mesh for rendering, although note that it is a little more efficient to collide with the nucleus ground plane than a mesh version. Also increase the friction a little on the nucleus node to keep the particles from sliding too much on the plane.
6. Cache the simulation. Set the time slider range to around 150, select the particle system and do "nCache: Create New Cache". When done, playback to view the animation so far. For faster playback set the particleRenderType to "Points". One can set it back to "Blobby Surface" later before rendering.
7. Attract the particles to the glass. Real water would tend to adhere to the glass a little and droplets would stick to the sides of the glass and roll down it. To accomplish this we can use the "Force Field" attribute on the glass to create an attractive force for particles that are very close to the surface of the glass. On the nRigid shape for the glass set the following:
Force Field = Single Sided
Field Magnitude = -4.0
Field Distance = 0.13

You may also wish to edit the field scale so that the force drops off to zero when the distance is less than the particle radius. In this manner the force then does not fight collisions. The left of the graph represents the strength at zero distance and the right at the max distance(Field Distance):
forceField.jpg

Cache the simulation again. Some of the particles should now stick to the outside of the glass and slide down it. If no particles slosh over the side or catch on the lip then move the cup over a little. The exact field magnitude and distance is important. Too great a distance and the particles will fly towards the glass as they get near. We use a value of 0.13 which is about twice the effective particle collision distance(given that the collideWidthScale is 0.5 and the radius is 0.13) Too great a magnitude and water will not drip off and will cling to the inside walls instead of filling. One other thing that can keep the particles from stacking along the inner wall of the glass is to use a bit of radiusScaleRandomize. If you want the drops to slide more slowly adjust the friction on the glass, but for this simulation we have kept the friction at zero, because we want as much sloshing in the glass as possible.

RENDERING USING BLOBBIES

 
1. Do a test render. First set the "Particle Render Type" back to "Blobby Surface". The water style particles have built in water style shading, but assume that you will be raytracing, preferably in Mental Ray. Also there are still numerous things that need to be done for good shading. First we can create a couple of lights, in this case I used a slightly amber colored key spotlight with raytraced shadows along with a dim bluish non-shadowed point light for fill. The glass and cup can get a blinn shader that is nearly fully transparent. An initial Mental Ray render at the preview setting may look something like this:
2. Set the refraction levels. If one simply enables raytrace refractions on the glass shader it will look like this:
Additionally lets set the shader's refractive index to around 1.3 and then in the render settings under quality increase the refractions and maxTraceDepth both to 6:
Note that the particles do not appear in the glass. One additionally needs to set "visibleInRefractions" true on the particle system(under Render Stats):
However note that this now starts to make the render slow. Tracing rays through the internals of the blobby isosurface is considerably slower than with a normal mesh, especially when motion blur is added. We will first show how to improve the look of the blobby rendering, then describe how to instead render with a mesh.
3. Adjust the blobby threshold on the particle shape. We can increase it a bit to make the surface smoother:
threshold = 0.85 ->This will also move the surface inward slighty.
In general to make smoother water one want more overlap between particles and at the same time a higher blobby threshold. Changing the radius will change the simulation, so unfortunately one also needs to lower the liquid radius scale to avoid changing the simulation( in case one wishes to recache). Note that with the particle mesh method this is not an issue as one can simply adjust the blobby radius scale instead of the radius. However "blobby radius scale" does not yet apply to the blobby raytracing( hopefully this will be added in future, making things easier ).
4. Adjust opacity. At this scale water is pretty much totally transparent so on the particle system set the opacity to 0.08.
5. Enable Motion blur. In the Render Settings quality tab set "Motion Blur" to "Full". This can make the render quite slow with raytraced blobby particles, so it helps to both lower the size of the blur and increase the time contrast(will be more dithered but significantly faster):
shutterClose = 0.4
timeContrast = 0.4
Here is the finished render of the scene pourBlobby.ma. In addition to refining the shaders a bit the raytracing levels have been increased. reflections = 3, refractions = 8, maxTraceDepth = 8, and shadows = 4. As well the rayDepthLimit on the spotlight is set to 4( allows shadows to be seen though droplets ).

RENDERING USING A MESH

 
1. Create the mesh: Select the particle system then do "Modify: Convert: nParticle to Polygons". This creates a mesh node connected to the output of the particle shape. The mesh may initially not appear if the triangleSize is too large(that should be the case here). Conversely if you are working at a large scene scale it might be initially very slow because the triangle size is to small for that scene scale. In such cases it can help to make meshTriangleSize large before doing the convert to poly.
Mesh raytracing is faster than the blobby raytracing, but can consume a lot of memory and time building the mesh. Also the mesh currently cannot be cached currently, because its topology changes over time. Thus you will generally only wish to display the output mesh for renders and keep it hidden during playback.
2. Set the output mesh attributes on the particle shape: The fastest mesh method is quads and this will require about 3 smoothing iterations. The meshSmoothingIterations take the initial set of polygons formed by walking a voxel grid and fit these to the particle density function, as well as make the polygons more uniform. A nice thing about the quads method is that we can further refine the mesh by using polysmooth (hitting the 3 Key). This is much faster than making the meshTriangleSize smaller. On the nParticleShape set the following in the output mesh block:
meshMethod = Quads
meshTriangleSize = 0.05
blobbyRadiusScale = 1.7
meshSmoothingIterations = 3
threshold = 1.1
motionStreak = 0.3
-> motion blur is not supported yet, but this is a partial workaround
3. Hide the particleShape so it will not display or render
4. Smooth the output mesh by selecting it and hitting the 3 Key.
5. Turn off motion blur for the particle mesh... either disable it on the particle output mesh shape or turn it off in the render settings. The motion streak attribute provides a bit of stretch on particle movement that helps compensate for the lack of blur.
6. Create a watery shader for the mesh: We do not wish to use the exact same shader as the particle system ("npWaterBlinn") because the particleSamplerInfo connections are not supported for meshes, thus we can't have per particle shading values when using the output mesh. Assign a blinn shader to the particle mesh with the following settings:
color = 0 0 0
transparency = 0.95 0.95 0.95
eccentricity = 0.07
specularRolloff = 0.16
->this makes edges more reflective than the center
specularColor = 1 1 1
reflectivity = 0.7
refractions = ON
refractiveIndex = 1.25
refractionLimit = 8
shadowAttenuation = 0.02
reflectionLimit = 3
7. Set the raytrace settings. These can be setup in the same manner as for blobby although one can generally use much higher quality settings without as high a penalty.
8. Add caustics. If we simply enable caustics in the MentalRay features tab then turn on "emit photons" on the spotlight it will look as follows:
To get sharp detailed caustics we will need to fire more photons from the light, which will take more render time. On the spotlight set the following:
photonIntensity = 5000
causticPhotons = 500000
-> could be less if the spread of the spotlight were smaller
On the tab "RenderSettings: IndirectLighting:Caustics" set
Accuracy = 200
Lets also se the shadow limit to 6 on the raytracing options as well as make the spotlight rayDepthLimit 6.
Here is a final image with also an added bluish point light(no shadows) for ambience.
This is the final render of the scene file pourMesh.ma. Before rendering it you should first cache the simulation. Also the particles are visibile in the file and the mesh is hidden. You need to show the mesh (polySurfaceShape1) and hide the particle shape before rendering. Note that the file is also slow to load because it initially generates the mesh even though it is hidden. One could workaround this by making the meshTriangle size temporarily large.

SURFACE TENSION

 
If desired one could additionally try to add effects like surface tension on the drops. This can be done by using the selfAttract attribute on the particle system, but be warned that currently this makes the simulation much slower(hopefully a surface tension attribute will be added to the liquid simulation in a future release, which would be much more efficient). One would make pointForceField = thickness relative, pointFieldMagnitude = 0, then adjust selfAttract for the desired tension.
In order to post any comments, you must be logged in!
Newest users comments View All 25 Comments
Posted by pandora51 on Oct 16, 2009 at 11:19 AM
Hi Duncan. Great tutorial as always. I was wondering if u had any tutorials to create light streaks with nparticles like in the following video:www.youtube.com/watch?v=IJLRHFkha30
Any help would be greatly appreciated. Thanx in advance.
Posted by duttyfoot on Aug 15, 2009 at 12:35 AM
duncan you are the man
Posted by Maya Guru on Jun 20, 2009 at 06:04 PM
awesome sir
u are great for a long i was looking for stuff
like water pouring but noe i got that
so nice of u sir.
Posted by AllenBrooks on Mar 18, 2009 at 09:09 AM
Duncan, Thanks so much for all your help here! The render turned out great - I really appreciate your time!

Allen
Posted by vicco on Mar 14, 2009 at 12:52 PM
Wow, looks pretty nice, but there's something about the geometry that's off, imho. Anyways, really cool :)