Buoyancy Problem

Started by
38 comments, last by Dmytry 19 years, 6 months ago
I'm not sure the correct way to solve this, but here's the problem. I've got floating, buoyant objects in my little demo. They are rigid bodies and calculate their buoyancy okay. The problem specifically is this... I have an object that is light (little mass) but a large surface area e.g. big cube with little mass. When I drop this into the water from a height, then the cube will obviously go underwater for a short period of time, but because of its size it displaces a large volume and this causes the cube to shoot up out of the water faster than it came down. Pretty much as soon as the cube hits the water its flying upwards into the sky! Do you add some kind of impact force when an object actually hits the water (e.g. goes from air to water) to basically stop/dampen its motion before the buoyancy takes effect or something? In fact, this may make it even worse. I'm not sure what to do. I could spend hours fiddling with the masses, cube sizes etc trying to find one that doesnt either fly up or sink. Getting things to float normally seems a little hard. I'm confused. I'm not calculating air resistance at the moment, but I don't see that affecting the upwards 'shooting' of objects. Any tips would be appreciated. Thanks.
Advertisement
i'm not very sure what you do, but it's looks like during your timestep your cube gets deep underwater, to the point where it shouldn't be, so it's pushed up too much and flyes out of water with bigger energy than when it hit.
It's problem with integrating 1st derivative discontinous forces.

Possible solutions: make energy conservation(that is, compute energy before hit, and after hit, scale velocity so energy will be smaller than energy before hit (by some damping). That at each timestep, total kinetic and potential energy is smaller or equal to previous), and/or use better integration method, but it will not eliminate problem completly (i don't know if rk4 is better in that case,but might be). Or handle that discontinuity analitically. (probably hard with arbitrary orientation of box).

Same will happen if you'll try to make a pool game(or pong) where balls have repelling force that depends to distance between balls, if distance is smaller than ball diameter. Like force=k*(ball_diameter-distance_between_balls). Energy will not conserve. So with pool game usual solution is to do collisions analitically.
Okay I see what you mean. I like the sound of the energy conservation approach and doing things analitically as opposed to just implementing the equations and seeing what happens.

Thanks.
And if you want me to be more specific,
Quick and simple solution, should work:
When object touches water, store it's velocity in variable v1

and when after leaving water it have velocity vel, you need to
vel=vel*(length(v1)/length(vel))*damping_constant_less_that_one;

With damping_constant_less_that_one=1 you'll have simple conservation of kinetical movement energy, it will probably bounce forever. With damping_constant_less_that_one=0.2 or so, you'll probably get good enough results.

It's looks like hack, but have some physical meaning - kinetical movement energy after bounce is always scaled by damping_constant_less_that_one2

****************************************************
If you want to apply conservation of energy even if it's partially under water, it's bit harder(and i don't sure necessary at all)... but more funnay.

how you can find energy of system:
It's simple to find energy of object(it's m*g*height + m*velocity_squared/2+rotation_energy), but what's with water? Same as with anything else.

(potential energy of water) = (height of center of mass of water) * (mass of water)

So we need to find height of center of mass of water, when you have floating object. It can be found in way very much like Archimedes law.

Let h0 = height of COM w/o object (COM it's center of mass)
let h1 - height of COM with object.
Let all heights is counted from water level without object.
Let hd = height of COM of "hole in water" created by sunken[sp] volume of object.

Let s it's surface area of water, let it doesn't significantly change when there's object.
Let v it's volume of displaced water. p*v it's mass of displaced water(p it's density). From Archimedes law, p*v*g it's your force to up...

Let M it's mass of all water

So we have
h1=h0+(v*0.5/s)*p*v/M - p*v*hd/M
(can't explain without drawing)

and water have potential energy
e1=M*h0+(v*0.5/s)*p*v - p*v*hd
and before had energy
e0=M*h0

so energy of water with floating object=
e0+(v*0.5/s)*p*v - p*v*hd

If surface is big, first term may be removed.
If object is fully under water, (- p*v*hd) it's center of mass of water in volume of object * depth under water.

edit: fixed typo.
Also, as about realism. In reality, when object hits the water, or leaves the water, it causes water to move, and water have inertia, and it's very complex thing, and there's some kind of impact force, of course... but your simulator surely have waay too long timestep to simulate it more-or-less accurately, it can't even do floating. Yes, "some kind of impact force" can make things worse as you think, because timestep is certanly too big.


So to make things be more realistic at impact you can only do that hack:
vel=vel*some_other_damping_constant_less_than_one;
....
v1=vel;//see prev post.


And it will be more realistic than what you do now, as well.
It's basically the same issue as with diverging spring systems. It's because of the retroactions at first or second order. This make the differential equations far more sensible to discretization (time steps).

The only decent solution is to have a much higher update rate for your physics. You need a higher frq. Google canonical game loop. There have been several threads at Gamedev.

You could locally have higher integration frequencies when any damping, spring buoyancy, well retroaction comes into play. AND probably some energy assertions to detect any unstability. But the best would be that your assertions are never triggered : find the right frequency.
"Coding math tricks in asm is more fun than Java"
Well at the moment, there is hardly any rendering and I just let both the physics and rendering run as fast as they want... so they must be well over 200 frames a sceond at the moment, though I've yet to check.

Though it may be tricky to keep track of the energy. It would be easy to check if the box was dropped and the energy amount stored before and then after it exits the water... but this is not always the case, the box could be underwater for a whole number of frames and things may have happened under water that also affect the energy - lift, drag and perhaps underwater collisons. Also I'm aiming for this system to be used for some boat physics, so it won't be a simple case of checking the energy before and after as the boat's velocity/direction etc. will be changing all the time, and then there are things like waves that can affect the volume displaced on a per frame basis.

ugh, this is getting confusing. :)
But, if there's waves/etc, not only buoyancy, it's whole different problem. If you want to model it accurately you'll have to do fluid dinamics, etc, very hard stuff. What you now do probably already physically have almost nothing to do with real water, except in static conditions.

When real object leaves water there's some suction.
When real object moves in water/enter, it moves water and it works like attached mass.(do you know that submarine accelerates like it's more than 2 times heavier than it is, because water have to move? so any model that doesn't count it will produce at least 2 times wrong results?)
So you should somehow attach mass to your object.... and it's also hard to do correctly.

Soooo.... if as simulation it's *very* inaccurate anyway, why not use hacks that if correctly applied will make it look more realistic?

Also, i think, waves itself can't make object to jump into air. (unless together with some pretty big piece of water)

******************

Another method, probably the most physically correct: when object hit the water, and underwater volume of object is v,
multiply velocity by (mass_of_object)/(mass_of_object+k*v*p)
Then, use (mass_of_object+k*v*p) as mass in all your acceleration calculations. In that formule, p it's density of water in your units.(i mean, 1000 kg/m3 or 1g/cm3 , depending to units)

Where , say , k=1.5 .

Explanation why it isn't very much of a hack, but have physical meaning:
There's water mass "attached" to object.When object hit the water it causes water to move, that is , water gets some of kinetical energy.

Think about what maximal possible acceleration air bubble does have? It have almost zero mass....

This is really used to model boats and other things including bubbles, except that IIRC k depends to speed.

2Charles:
I think, if he'll model water in not so inaccurate way(not as nearly ideal spring), there will be enough damping at impact that will mask all integration problems. Yes, it's needed to increase timestep to model spring better but why assume water is a spring? Even if it's not a water but helium in superliquid state[grin], there will be damping on impact due to turbulent dissipation. There will be attached mass, greater or equal to mass of vater in volume of underwater part of object.
Jump will not be totally elastic because even superliquid will get some of kinetical energy.
Maybe model the viscous drag of moving through a fluid as a sort of damper. Then an object (like your low mass/high volume) that can generate high speeds in the fluid will be slowed by higher damping forces, as it is based on the velocity. It could also represent the added force needed to push the mass of water out of the way.

Alternately, somehow find the volume of water (roughly) that also must move when the object displaces (or stops displacing), then you can find the mass of it and accelerate the body as though it had massItself+massWaterMoved. I suppose you could do this if you know the body's velocity and dt between frames, as well as a surface area (probably normal to the velocity). That would create a sort of volume (surface area x distance it will move).

It's a hard thing to model accurately, as even in design of boats/cars/etc engineers end up using a windtunnel and not equations to predict the behavior of fluids around bodies. So as dmytry said, you're probably better off with a few well thought out hacks to make it behave how you want.
It may help if I explain how I model my objects. I basically model buoyant objects with a low polygon triangle mesh (like a collision mesh). I calculate the area for each triangle as that's needed for the volume, drag and lift calculations, I also store the velocities of the centres of each of those triangles (as each triangle may have a different velocity if the body is rotating).

To calculate the volume a triangle displaces I do this:

1. For each triangle centre get the water height at the x,z coordinate.

2. If the triangle is underwater, then fire a ray from the triangle directly upwards to a distance of t (t = distance from triangle centre to water level).

3. If the ray hits another triangle then it means its displacing water only upto that point (e.g. boat is fully underwater). If the ray does not intersect another triangle then the boat is partially underwater (e.g bottom of the hull only).

4. Use that distance to calculate volume displaced (triangle area * distance below surface or triangle intersection * normal.y)

So it's a pretty good estimate based system for calculating the volume displaced... But something just struck me, based on drag...

At the moment I implement drag by checking triangles that have normals pointing in the relative direction of the triangle (dot product test), but how about if I add 'suction' too, so for triangles that are underwater whose normals are pointing AWAY from the triangle's velocity then use that to create a suction force that sort of represents the water that needs to fill the empty volume that the triangle is leaving behind it. If that makes sense at all? It might counteract this box flying into the air, as the box will be slowed down as it is 'sucked' back down. What do you think?

This topic is closed to new replies.

Advertisement