Simulating a Tree in Box2dWeb

Simulating a tree in Box2D is not as trivial as it sounds.

A tree will sway gently in the wind, spring back into shape after an impact, provide resistance, and break when enough force is applied.

The dynamics of a tree also change depending on where it is interacted with. For example, pushing a tree at the base has a different effect than pushing at the top.

Unfortunately, Box2D does not have a joint that can replicate this complicated behaviour out-of-the-box so we will have to make our own.

Building a Foundation

The core of a tree is the trunk so that is where we will begin. We know the trunk needs to be flexible so we can construct it from a stack of narrow boxes and connect them to each other with RevoluteJoints. The base of the tree is connected to the static ground object so it will become rooted in place.

For beginners to Box2D, keep in mind that shapes have a centre origin. This can be tricky when initializing shapes and determining relative anchor positions. The example below shows a shape SetAsBox(x,y)

basic-revolute

The Result

The result is a perfectly balanced chain standing end-to-end. While fun to play with, this “tree” is a tad bit flexible for its own good…

tree-v1

Try the Demo

Restricting Rotation

Luckily, Box2D provides an easy way to deal with this situation through enableLimit. It allows us to restrict the rotation of a joint by specifying a lowerAngle and upperAngle (in radians).

For those who think in Cartesian Coordinates, Box2D sets its angular origin at 90 degrees. This works out well for this example since we are stacking along the y-axis. But in most cases it is something to keep in mind.  

revolute-joint

The Result

By simply restricting the rotational movement we transform (as if my magic) a chain into a wilting tree! While still fun to play with it feels lifeless.

tree-v2

Try the Demo

Motoring

To get our wilted tree back to an equilibrium position we can use motors. In Box2D a motor provides a rotational force to a joint. Once enabled you simply specify a velocity and (optionally) a torque.

Note: Box2D uses the term speed, however, it actually signifies a velocity since this value determines the direction of rotation. A positive value rotates clockwise and a negative value rotates anti-clockwise.  

Motors provide a constant rotation with each timestep. For this reason, we do not set an initial velocity. If we do the tree will just curl in one direction. Instead, we determine the speed dynamically with each call of update().

We set the the speed of each joint to the negative of its angle of rotation.

At small angles there will be a small speed, at large angles there will be a large speed. This creates a nice smooth transition. The graph of this function is shown below.

tree-velocity

Note: The default torque is far too low to overcome the joint friction. In this example, we manually set the torque of each joint to 500.

The Result

Our wilted tree will now awkwardly right itself before swaying to a never-ending song only it can hear. While awesome, not exactly what we were going for.

tree-sway

Try the Demo

Enter the FlexJoint

How can a linear velocity provide such jittery motion? The answer is torque. We are using an arbitrary value for torque which clearly is not enough to support the structure at large angles. The joints are slipping!

We can smooth out the transitions by dynamically calculating torque relative to the angle of the joint at every timestep.

When the angle of a joint is at its maximum value (in our case 30 degrees) we want our torque to be its highest. Essentially we are matching the torque with the amount of friction the joint must overcome. This balance allows our smooth velocity to work as intended.

flex-joint

Joints are each assigned individual torque multipliers. This normalizes the torque to be relative to the amount of load they are moving. The bottom joint must rotate the whole tree structure and will therefore require a higher max torque than the topmost joint which only needs to move one segment.

Note: To eliminate the perpetual swaying we ignore the Flex Joint logic when at small angles. This prevents the quick switching of directions back and forth right before equilibrium. 

The Result

Our tree now flexes and returns upright naturally with only a few extra calculations.

tree-v3

Try the Demo

Finishing Touches

The constants and algorithms used in our Flex Joints can be tweaked to provide accurate dynamics for different types of trees. Adding branches and overlaying graphics will come soon as the project develops.

Thanks for sticking around. Don’t beat around the bush, leaf your comments before you split.

0

3 Comments

  1. Ctibor Laky

    Nice article.. good for begginers in box2d as I am… example code snippets would be nice addition 😉 Thanks

  2. Asheesh

    Awesome! 😀

    • Asheesh

      I was wondering, if there is a more accurate way to use stiffness for calculating torque and angspeed.

Leave a Reply to Asheesh Cancel Reply