Email Updates RSS Subscribe
Line

This blog is created and maintained by the technical team at Hook in an effort to preserve and share the insights and experience gained during the research and testing phases of our development process. Often, much of this information is lost or hidden once a project is completed. These articles aim to revisit, expand and/or review the concepts that seem worth exploring further. The site also serves as a platform for releasing tools developed internally to help streamline ad development.

Launch
Line

Hook is a digital production company that develops interactive content for industry leading agencies and their brands. For more information visit www.byhook.com.

Line

Fuzzy Physics Pt. 2 – Constraints Applied

Line
Posted on January 22nd, 2010 by Brad
Line

In my last post I went over basic velocity-less integration and constraint systems to create some simple and easy inverse kinematic dynamics.  Before moving on to more complicated fair like rigid bodies and particle systems from that groundwork, I wanted to try and apply those basic principles to something a little more tangible.  After all, this is about breathing pixelated life and death into the computer screen.

Several of my early experiments with Verlet and the resultant IK chains started taking on a remarkably organic feel as forms not unlike tentacles and wings started emerging.  So, I figured a nice little test of this system would be to make a self propelled code-organism with all its movement and character imparted by dynamics rather than timeline animation or tweening engines.  Aside from being affected and propelled by forces, I want to try and push this system to apply basic animation principles to impart some additional character in its movement.  A tall order perhaps.

To keep things simple, I’m going to model the motion after an aquatic invertebrate.  Broken into steps, each move should consist of:

  • find a new target position
  • anticipate the motion by moving in a direction opposing that target position
  • move towards that target position, slightly overshooting it
  • settle into that position
  • and for some additional pain, all this while conveying a sense of volume and pliability through squash and stretch

While fairly simple on their own, incorporating them into a dynamic motion system that is as simple and reusable as it is expressive can be quite a mind-bender.  So lets dig in from the middle with a heroic dose of spring physics.

Driving the Motion: Spring Physics

Giving a short consideration to the issue of moving from point A to point B, the following options were the most obvious:

  • per-update interpolation of current position towards the target position along the lines of: a=a + (b - a) ratio
  • interpolate the current position towards the target position using a tween engine (similar above, only our ratio is determined by the tween function)
  • steering behaviors, namely the ‘Arrive’ behavior
  • springs!

The spring option became the obvious choice mostly because of the requirement of anticipating our moves, which with the other systems requires more complicated and arbitrary calculations to cram that in.  Also, spring force is highly dynamic, and while the arrive behavior would grant us a certain amount of that, I find it imperative to make the antic as easy to implement as possible because:

  • I am lazy

Spring forces are a really simple and great way to implement dynamic motion.  Whereas friction and other forces require additional calculations of surface normals and relative velocities, for basic linear springs, all you need is  a displacement, as stated by Hooke’s Law:

F = -kx

where:

k is our elasticity constant

x is our displacement (in the form of a vector or scalar, depending on your number of dimensions)

What this means is that the force applied by our virtual spring is directly proportional to to displacement of our object from its ‘home’ position, where the spring is at 0 stretch.  But the really fantastic part of this is that the spring will take care of all the acceleration and deceleration for you as the object moves.

Note that Hooke’s Law applies only to linear elastic forces, when your springs start extending beyond their natural limits, other forces take over, but for most cases this is not an issue.


Get Adobe Flash player

The above example is a simple demonstration of Hooke’s law applied to the motion of a point-mass, which will essentially serve as the motor moving forward.  This spring force is integrated via Jakobsen-style Verlet, however, you could use just about any other integration scheme for a similar effect.  The trailing ‘orientation’ point is moved via a single-direction rigid constraint to help give our object a better sense of direction.  Here the spring force (gray) and velocity (red) vectors are drawn out to help visualize exactly how the motion is being generated.  Here is the psuedo-code:

// first, find the 2D displacement from our position to our at rest position
var displacement:Vector2D = lead.position - target;
 
// multiply that by the negative of the elasticity constant (adjust this number to your liking)
var force:Vector2D = displacement * -0.9;
 
// integrate that force into our movement via Verlet
// the numbers preceding our current and previous positions are the Jakobsen 'drag' values noodled to taste
// without that 'drag' the spring would oscillate endlessly, if you're into that
// note that i am also using a determinate timer so that my updates run at a consistent interval
// with a time delta per update of about 0.25
var x:Number = (1.7 * lead.position.x) - (0.7 * lead.previous.x) + force.x * timeDelta * timeDelta;
var y:Number = (1.7 * lead.position.y) - (0.7 * lead.previous.y) + force.y * timeDelta * timeDelta;
 
// reset our previous position to what was our current going into this time step
lead.previous.x = lead.position.x;
lead.previous.y = lead.position.y;
 
// update the position according to our motion integration
lead.position.x = x;
lead.position.y = y;
 
// then you would apply constraints, etc.

All you have to do then is change the objects position or its rest position and it will start moving.  With that basic foundation for motion in place, lets add in the anticipation to help give it a feel of self-motivation.  With Verlet and springs, this becomes a simple matter of just moving our  object by a fraction of the displacement between our current position and the target position, but away from the target position, the integration takes over from there.


Get Adobe Flash player

The example above should illustrate the subtle effect of telegraphing the move with an antic.  Just by moving the object away from the new target a small velocity is imparted, which is slowed until the spring reverses the direction towards the target.  There are slight variations that could be used depending on the desired result, but the position shift does the job well and is as simple as it gets.  Here is the psuedo-code on the mouse down:

// as we did for the spring force calculation, get the displacement vector
var displacement:Vector2D = lead.position - target;
displacement *= -0.2;
lead.position += displacement

With a freakishly small amount of code (outside of UI and a 2D-coordinate storage class) I’ve established a basic motor for the code-ling so it can swim about on stage, in a hopefully appealing manner.  But we can still add a little more life to it using these basic tools.

Adding Form: Squash and Stretch

While the antic works well and good to add some illusion of life to our codeling, to really sell it we need to find a way to show how its motion is affecting it other than position alone.  A quick and easy way to do this would be to use a sprite animation of it scrunching up and extending out, but that wouldn’t be nearly as fun as doing that within our dynamics system.

Here is where our orientation point will really come into play.  What we’ll do here is add a little inertia to that point and soften up the rigid constraint pushing it away from the lead point, effectively making it a pliable spine.


Get Adobe Flash player

The effect should be quite subtle until you slow it down, but either way you should at least get the feeling that the object is stretching and compressing along with its movement, with a slight overlap in the action. Here is where the math starts getting a little more complicated. While I am still using the same integration technique as the lead point, I am dampening movement of the orientation towards the lead point separately from the movement tangential to that.  This is merely an aesthetic choice to reduce the rotation of the orientation point around the lead point.r.

The modified dynamics update now includes (note that while this smells slightly different from the above integration of the lead point, it tastes exactly the same)

// get the velocity going into this time-step (this is equivalent to the "2.0 * position - 1.0 * old" portion of the Jakobsen formula)
var velocity:Vector2D = orientation.position - orientation.old;
 
// we want to break this velocity up into components relative to the displacement to the lead point
var displacement:Vector2D = lead.position - tail.current;
 
// to get the component parallel to the displacement we project the velocity onto that displacement
 
// first use the dot product of the two vectors to find a ratio by which we are going to scale our projected onto vector
var dp:Number = velocity.x * displacement.x + velocity.y * displacement.y;
var ratio:Number = dp / (displacement.length * displacement.length);
 
// then use the following formula
var parallel:Vector2D = new Vector2D ();
 
parallel.x = displacement.x * ratio;
parallel.y = displacement.y * ratio;
 
// the perpendicular component is then just the parallel component subtracted from the original
var perpendicular:Vector2D = velocity - parallel;
 
// dampen independently
parallel *= 0.7;
perpendicular *= 0.5;
 
// then back to our standard integration, combining the two components back together
tail.old = tail.current;
tail.current += parallel + perpendicular;

That code will allow us to impart some inertia on the orientation point, letting it drag and overshoot based on the lead points movement. But before setting that in motion, the constraint logic needs some modifications, otherwise it will null all that delicious overlapping action out. You may have noticed that the movement of the orientation point is now somewhat springlike, but that isn’t accomplished through a spring force as with the lead point but by the new ‘soft’ constraint set-up, which gradually corrects the constraint each update.  A big issue I encountered with a soft unilateral constraint combined with inertia is the inevitable point at which your moving point crosses through its reference point. While you could use some sort of gradient correction strength, for simplicity I set the constraint up with with capabilities for:

  • over-compression
  • over-extension
  • normal correction

So while the constraint will gradually correct towards its preferred length under normal conditions, it drastically increases the correction for cases of extreme compression and extension to try and ensure that the point doesn’t pass through its reference, a sort of hybrid prismatic joint if you will.  Here is the pseudo-code for the new constraint relaxation:

// using our displacement vector from above
var displacement:Vector2D = lead.position - orientation.position;
 
// the ratio of that displacement vector we will be correcting by
var ratio:Number = 0.0;
 
// we can also vary the strength of correction based on which case
var strength:Number = 0.0;
 
// we have 3 cases, over compression, over extension, and normal correction, otherwise nothing needs to be done<
// the ratio variable will be defined depending on which case we are in
if (displacement.length < minLength) {
 
	ratio = (displacement.length - minLength) / displacement.length;
	strength = 0.8;
 
} else if (displacement.length > maxLength) {
 
	ratio = (displacement.length - maxLength) / displacement.length;
	strength = 0.8;
 
} else if (displacement.length != relaxedLength) {
 
	ratio = (displacement.length - relaxedLength) / displacement.length;
	strength = 0.1;
 
}
 
// then, just correct the position
displacement *= ratio * strength;
orientation.position += displacement;

With a solid line of action in place for direction, squash and stretch, I want to add a couple more points/constraints to illustrate the internal action as well as to establish a solid volume to the object.


Get Adobe Flash player

Simply by adding 2 points and 5 additional constraints (2 from each side to the lead and orientation points, and 1 between the points), I have added a squash effect as the object compresses both while anticipating the move as well as during the recoil, all without adding complexity to the dynamics update with angle calculations and other scary math.  But what I’m really interested in with these points is the ability to link additional structures to them, like tendrils and tentacles.

The constraints used are extremely simple soft unilateral constraints and a basic prismatic constraint between the two side points, so there are occasions in which the constraints collapse and buckle during extreme movement.  But because the motion is intended to be a bit more subdued, I’m not going to worry about bugs that will eventually be voided out.

Hopefully I’ve demonstrated how with a few constraints and springs you can add some more life to dynamic movement, and its not too hard to imagine some cute little beady eyes and nasty, big, pointy teeth on my sparse vector graphics.

Line
1 Response to “Fuzzy Physics Pt. 2 – Constraints Applied”
  1. Jason says:

    This is sick. Thanks!


Leave a Reply

*

Line
Line
Pony