Updated: Nov 14, 2022
My goal with this project was to learn the basics of crowd simulation for an upcoming project at SCAD animation studio. The film will include the simulation of lots of re-animated skeletons, so zombies seemed like a fun choice.
The crowd simulation consists of two components agents, and simulation.
Agents are packed representations of the character instanced in the simulation. Crowd simulation requires specific properties added to the objects used in the simulation, this is stored on primitive attributes. All this information is stored in an agent definition. An agent definition includes:
• The character model (as packed geo)
• Clips ( animations the character can perform)
• Transitions (information about how agents transition to other clips)
• Ragdoll colliders and configuration
• Agent properties
The crowd simulation utilizes the agent definition to inform how that agent should behave when acted upon by forces. Much like other simulations the crowd solver responds to different external inputs. However instead of driving only positional information it controls the agent behaves. Behaviors are known as states and can be triggered by a variety of inputs, such as time, POP forces, RBDs, proximity, or VEX.
Technical guide: Agents
For this project the character rig and mocap data was downloaded from mixmo.
The first step of building the agent was to add clips. Agent clips can be added from motion clips, a packed representation of each frame of an animation (new in KineFx). To build a motion clip the input animation must be matched in scale to the target Skeleton and the connections between the source skeleton (the one with animation) and the target (skeleton that deforms your character). This outputs a possible skeleton, this can be animated and tweaked using KineFx for Ik’s or using a RigPose node.
Fig2 & 3. Motion clips for walking and standA animations.
The zombie agent has 5 clips, walk, standA, standB, deadA, and deadB. To add more variation each of these poses are mirrored and added a new clips. Mirroring is accomplished using a rig mirror pose with the position matching set to naming and similarity.
Fig4. Node network to setup and mirror motion clips
Another key element of the clips is locomotion. Instead of using a static value to drive the position in the simulation we can extract the Z and X movement and apply that motion instead of static values. In most cases locomotion is extracted from the hips.
Fig 5. Extracted locomotion from the hips of the walk.
Rag doll colliders can also be added in the agent definition as well using an agentCollisionLayer node. Farther downstream the limits of each joint are controlled using an agentConfigureJoints node. The rag doll is not part of the crowd solver, but the collision objects must be added in the agent.
Fig 6 & 7. Ragdoll colliders and joint limits.
The final step of configuring the agent is to define the transitions between clips. Using the
agentTransitionGraph node you can define which clips blend into which and the frames transitions can occur. By default Houdini tries to generate this graph automatically however I had to manually set it up because of the differences between poses I needed to blend.
Fig 8 & 9. Crowd transition graph and parameters for a transition.
Technical guide: Crowd Simulation
To begin the crowd simulation you must generate a crowd. This is accomplished with a crowdSource node. The crowdSource can take in input surface, and even cooler you can paint a density attribute to control distribution of the crowd.
Fig 10. SOP network of the crowd. The output feeds into a DOP net. Fig 11. Paintable density
The agent constraints are generated through a shelf button I used to incorporate the ragdoll.
Inside the DOP net the simulation is pretty straightforward, each agent has three states, Dead, Walk and Ragdoll. When triggered to talk they begin to transition to that state, animating any clips between the current and end clip. Meaning when we transition from dead to walk it actually transitions from dead to stand to walk.
Fig 12. DOP network.
Within this simulation only two tiggers are needed for the desired results. First a time based trigger wakes up the zombies, causing them to stand and walk toward a target point (this is accomplished through a POP seek node and POP avoid obstacle). The second trigger causes them to rag doll when they enter a bounding box around the end of the ground plane, gravity forces them to fall off the cliff.
The rag doll is not part of the crowd solver, instead it is bullet solver, so Houdini uses a multi solver to swap between the crowd and bullet solver when rag doll is triggered. For the Ragdoll simulation I needed to add the brick ground, because the ground is dense I created a new lightweight collision using VDB conversions.
Fig 13. RBD colliders on zombie agents and static collider
Description of problems encountered and solutions:
Problem: Tons of clipping! The crowd solver has an avoidance to avoid agents intersecting, I was also using a POP steer to keep them from colliding with the pillars. In some cases both conditions could not be maintained so they would clip through either another zombie or pillar
Solution: *Not a production solution* I played with the force weight as well as the number of zombies and spawning locations to try to minimize two agents being super close when moving between pillars. Problem: Foot sliding! Solution: A lot of this is handled by the foot locking options on the crowd solver. Another huge benefit came from using a single foot as the locomotion driver instead of the hips. I think using a more standard clip (non- dragging feet) would help fix this, or finding a way to specify when the foot is planted.
Problem: FBX animation goes below the ground plane, especially in standing clips.
Solution: Using the rigPose Node I was able to manually layer in fixes to the clips that fixed these issues.
Problem: Ragdolls causing flipping, crazy deformation and super high speed movement.
Solution: I added a bit of stiffness to the ragdolls and that had a huge benefit to the the crazy flipping. This way the zombies would try to semi maintain the pose of the clip at first blending into full rag doll. The crazy over 180 degree twist was handled by adding limits to the agent joints using the agentConfigureJoints node.
Problem: Rendering in redshift causes the crowdsource icon to show as geometry
Solution: Object merge the output geometry from the crowd into a clean container and hide the container with the crowd source.
Problem: Cooking times. Super slow to adjust things in the Agent or super slow playback from DOP sim. Loading the scene was super slow from re-cooking the ground.
Solution: Cache out things whenever possible. The agent definition can be cached,
Fig 14. Cached out files. Used in agent definition, environment geo, and DOP.
This was an incredibly fun project! There are definitely things I could have improved on, but I feel prepared to attack another crowd simulation. Moving forward I would like to use one of my rigs as the agent rig, I think that will be pretty straightforward to export as an FBX with only the skin and skeleton. I would also like to learn more about the mocap process and how I might be able to incorporate it in other areas of my career. If I were to use this in a production I would try to cleanup the Mocap in Maya first to fix issues there.
Fig 15. The bottom of the cliff the zombies fall down. (AKA really good deformations…)