I've been building a buoyancy system using JME-Physics, and I've noticed some strange behavior with the application of forces on objects that have very small densities (in the range of 0.001 to 0.0001, which are about the densities of air and helium respectively).
Its entirely possible that its a bug with my code, but I just wanted to check if anyone knows if the physics engine would respond unusually to low densities.
Actually, I've resolved the problems I was having (they were my fault, as predicted).
sbayless, could you please post your full experience with this?
I am having trouble with a system that includes small densities, and perhaps knowing what was wrong in yours could help others.
Thanks!
Absolutely. I don't know if you'll really find it very useful though.
I've built an add-on for jme-physics that simulates realistic buoyancy effects. Part of this included adding water/air friction. I did all my initial testing with water (which has a density of approx 1 g/cm^3, the same as the default material). Water is also a relatively viscous fluid, so it exerts a lot of friction on objects that are moving through it.
So after I'd put everything together, I wanted to test it with air, as opposed to water. So I set all the densities down by a factor of 100 or so, but what I found was that rotational friction caused very odd behaviour - objects would spin wildly and impossibly at the slightest perturbation, instead of slowly righting themselves as they did in water.
Rotation friction is applied by grabbing the angular velocity of the physics node, inverting it, doing some magic with it to account for the resistance of the object, and then applying that as torque. This approach worked without a hitch with large densities, so I'm not sure why it wouldn't work here - though it might come down to a rounding error somewhere, magnified by the larger impact that a similar sized force will have on a very light object.
When I said that the problem was my fault, that was only partly true (while, it might still be entirely true). I am still not sure why objects were effected the way they were by the forces being applied to them, but what I did realize was that I was applying far too much force to them - because I didn't account for the much lower viscosity of air. When I adjusted friction downwards to match viscosity properly, things behaved mostly normally. However, if I put the viscosity much higher (which is not implausible; someone might was to simulate a very viscous fluid with the density of air) then the problem comes right back.
What I've done to try and limit that effect is to cap the torques and forces that buoyancy/fluid friction are able to exert. Actually, I'm capping the acceleration that they can cause. I pass the requested torque (or force) through a little method that then checks if the magnitude of the torque is too large, and then multiplies it by a factor to decrease it as needed. This seems to help things a little bit, but does not entirely eliminate that strange behavior. Possibly, playing around with the maximums will do the trick.
Like so:
private static final float MAX_LINEAR_ACCELERATION = 200f;
private static final float MAX_ANGULAR_ACCELERATION = 200f;
private void applyLimitedForce(DynamicPhysicsNode physicsNode, Vector3f force, Vector3f position, PhysicsCollisionGeometry geometry)
{
float mass =geometry.getVolume() *geometry.getMaterial().getDensity();
//Limit the force being applied
float magnitude = force.length();
if (magnitude/mass>MAX_LINEAR_ACCELERATION)
{
float factor = (mass*MAX_LINEAR_ACCELERATION)/magnitude;
force.multLocal(factor);
}
physicsNode.addForce(force, position);
}
private void applyLimitedTorque(DynamicPhysicsNode physicsNode, Vector3f torque, PhysicsCollisionGeometry geometry)
{
float mass =geometry.getVolume() *geometry.getMaterial().getDensity();
//Limit the torque being applied
float magnitude = torque.length();
if (magnitude/mass>MAX_ANGULAR_ACCELERATION)
{
float factor = (mass*MAX_ANGULAR_ACCELERATION)/magnitude;
torque.multLocal(factor);
}
physicsNode.addTorque(torque);
}
I've set MAX_ANGULAR_ACCELERATION and MAX_LINEAR_ACCELERATION at around 200, but that should be adjusted.
sbayless said:
I've built an add-on for jme-physics that simulates realistic buoyancy effects. Part of this included adding water/air friction.
that sounds very interesting, btw - care to post some demo on the showcase board?
Yes, I am planning to, just as soon as I get it cleaned up and put together a concise test package.
Some of the physics behind it are very, very hand-wavy, but it still manages to produce reasonably realistic effects.
Rotation friction is applied by grabbing the angular velocity of the physics node
Why not just use a friction call back?
Why not just use a friction call back?
Well, I haven't used friction callbacks before now, so I hadn't thought to do so. I won't have time this week, but I'll look into it (although my current method does work most of the time, currently).