Motor Flash Physics: fancy buoyancy

Buoyancy is a force that acts on a body which is immersed in a fluid. This force can be divided into a static and a dynamic component. The static component acts on a body that rests in a fluid – it determines if a body floats or sinks and it always points in the opposite direction of gravity, whereas the dynamic component is always directed against the movement of the body, so it can be used for a ship that moves horizontally or a body that drops from a height into the water.

The static force is equal to the weight of the displaced water, which can be calculated by clipping the polygon against the plane that defines the water level. An efficient way of doing this is to triangulate the polygon and clip each triangle to the water plane, which is faster than clipping the complete polygon against the plane. Thanks to Erin Catto for pointing that out.

The dynamic force acts as a damper and is proportional to the velocity of the body in the fluid. To calculate this physically correct would be overkill because you would have to use drag. So its just approximated by using the submerged area. And of course all forces act on the centroid (center of mass).

Since I am still using the slow (non-optimized ;-)) AS2 version of the motor engine I provided a flash-projector for the demo so you can play around with the demo at a descent speed (try to stack the boxes on top of each other). When the AS3 port is finished (hopefully soon) I will recompile and enhance all demos.

Now watch or download the buoyancy demo!

Operator overloading

I am updating and converting my physics code to AS3 at the moment, and one thing I really miss in AS3 is operator overloading which would make your code more legible, especially when you are using vectors and matrices a lot.

Here you sum two vectors, multiply the result by 5 and finally make the vector perpendicular to itself. This not only invokes multiple function calls, but it produces “spaghetti-code” that is hard to read.

vec_a.getSum(vec_b).getMul(5).getPerp(); // PERP((A + B) * 5)

Hence static functions are better and the parenthesis structure is easier to recognize:

Vector.perp(Vector.mul(Vector.sum(vec_a, vec_b), 5));

This approach has the benefit that you can store the function in a local variable (or pass as a parameter) and gain a little speed in AS2 if it is invoked a lot.

var mul:Function = Vector.mul;
var sum:Function = Vector.sum;
var perp:Function = Vector.perp;

for (var i:Number = 0; i < 100; i++)
{
    perp(mul(sum(vec_a, vec_b), 5));
}

Again, this becomes very nested if many expressions are concatenated.

On the other hand some languages like C++ come with a feature called operator overloading, where you assign a function to an operator:

// adding two vectors
Vector operator + (const Vector &V) const {return Vector(x+V.x, y+V.y);}
// multiply by scalar
Vector operator * (float  s)        const {return Vector(x*s, y*s);}
...

So now the expression simply becomes:

perp((vec_a + vec_b) * 5);

Sadly, AS3 doesn't support such a thing, so you have to stick with static functions and simply expand the vector into its components when it gets messy:

result.x = (vec_a.x + vec_b.x) * 5;
result.y = (vec_a.y + vec_b.y) * 5;

result.perp();

This is OK for 2 dimensions, but in 3 dimensions, you start to write many lines... ;-)