Jump to content
  • Advertisement
CelticSir

Algorithm Buoyancy problem for a boat

Recommended Posts

Posted (edited)

Hi

 

I am trying to create simplistic model for boats floating in water in Unity using PhysX but i am not understanding how to get it work properly.

 

I use a single rigid body with a centre of mass as the red dot. Its below the ship's mesh as i read having a lower centre of mass made it more stable. Though i cannot get it to be stable anyway.

 

Each green sphere is a buoyancy force calculation which has this code, and it applies the force upwards at the spheres position:

         _volumeUnderPlane = VolumeBelowPlane();
        if (_volumeUnderPlane > 0)
        {
            // P = 1027 (approx density of water at sea level)
            var force = -_volumeUnderPlane * Physics.gravity * P; 
            _parentRB.AddForceAtPosition(force, transform.position,ForceMode.Force);
        }

Where Volume below the plane is calculated as:

    private float VolumeBelowPlane()
    {
        //water level is always 0 for now
        //math based on https://en.m.wikipedia.org/wiki/Spherical_cap
        var dist = -transform.position.y + _radius;
        dist = Mathf.Clamp(dist, 0, 2 * _radius);
        var dist2 = dist * dist;
        var frac = Mathf.PI * dist2 / 3f;
        var volume = 3 * _radius * frac - frac * dist;
        return volume;
    }

But the result is totally unstable, this is how it looks with a lowish mass:

https://i.imgur.com/LLoVzP5.gif

With a high mass it looks like this:

https://i.imgur.com/WNrO33z.gif

 

I am trying to replicate how assassins creed does it, they used spheres to approximate the buoyancy without it being too computationally heavy, yet they didn't go into any details on how they did the math for it but they did post this image of it:

https://www.fxguide.com/wp-content/uploads/2012/12/immerse_spheres.jpg

 

Am i doing any thing wrong with my math here? I don't know why its so unstable for me.
 

Edited by CelticSir

Share this post


Link to post
Share on other sites
Advertisement

for performance issue i put 20 ships on a dynamic ocean grid and used a simplified 3d volume of a ship (still had a ship hull but with less polys) and i didn't find any performance issues, at all (not to mention it was tested on phone, not to mention calculating form drag, skin drag etc. slicing each ships hull with water planes, determining new hull under the water and computing all the stuff.... really using spheres seems lame.

 

Anyway It looks like your inertia tensor is not calculated properly or you attach the force way where you shouldnt. Maybe you use local notation instead of other one (global or else or else), or even you dont play with real numbers - you should start with real numbers

Aside of these functions of yours with some unknown behavior, which i wont help you with cause i dont use 3rd party engines.

The first thing you should consider is to match buoyancy with the mass of the object, it has to stay afloat

 

then second thing is the fact you maybe cant even code the thing  liek this instead of using some wiffy functions like add force add point... not to mention transform.position THE HELL???, forcemode.force JEEEZUS!!

 


/*
 * Buoyancy effect
 * ******************************************************************************************
 */

vec3 cog2cob_vec 	= vectorAB(pos + ROTATION_MAT * CENTER_OF_GRAVITY, CENTER_OF_BUOYANCY);
vec3 buoyancy_force = vec3(0.0, 1.0, 0.0) * (GForce * SUBMERGED_VOLUME * 999.1026);


vec3 ETorque = cog2cob_vec	*  buoyancy_force;

vec3 elements_torque = ETorque;

then you could

result_force = gravity_force + buoyancy_force + drag_force + thrust_vec;

mat4 inv_rot = ROTATION_MAT;
inv_rot.Inverse();

vec3 local_torque = inv_rot * elements_torque;

vec3 EAngAcc = vec3(0.0, 0.0, 0.0);

if (!betweenorequal(-epsilona,epsilona, Ixx))	EAngAcc.x = local_torque.x / Ixx;
if (!betweenorequal(-epsilona,epsilona, Iyy))	EAngAcc.y = local_torque.y / Iyy;
if (!betweenorequal(-epsilona,epsilona, Izz))	EAngAcc.z = local_torque.z / Izz;



EAngVel = EAngAcc*dt;


AngVel = AngVel + EAngVel;

vec3 vLocalAngularMoment = (AngVel*dt)*RAD_TO_DEG;



vec3 accel = result_force / mass;

vel = vel + accel*dt;
pos = pos + vel*dt;

this one is quite important - angular velocity aint calculated as new each frame, instead you add it up.

 

Secondly you add a damping function that reduces chances of getting NANs and divisions by 0

by the first code of the physics frame

    damp(&vel, 10.0, 0.007);
    damp(&AngVel, 10.0, 0.0005);

 

 

 

not to mention drag caused by other parts of the ship etc, sucction force imo is a reaction so you shouldnt consider calculacting that

Share this post


Link to post
Share on other sites
Posted (edited)

Why do you need the green spheres? Can you not calculate the buoyant force precisely, computing the water pressure at each face?

Edited by alvaro

Share this post


Link to post
Share on other sites
Posted (edited)

They are a simplifications. A real ship gets overwhelmingly complicated quickly. To precisely calculate the forces in such a dynamic system one would at least need:

- the shape of the hull and the construction waterline.

- center of mass and center of lift to calculate righting moments from the static forces. Weight distribution and heel angle play a role here.

- pressure point of the wind force, to calculate righting and turning moments induced from the sails. Easier for a for- and aft rigg (the typical sloop), but a tall ship like in the op is something much more complicated (basic Wikipedia article on wind forces).

- other dynamic forces, resulting from movement of the whole thing in water and wind. These can be decisively strong when underway. Example: rudder and keel, drag and differences in displacement.

My naive idea would be, if one wants it somewhat more realistic, to pre-calculate or -define polar curves for the moments and look up values for certain situations, interpolating between them. Don't ask me for detail, pls 🙂

 

For a more simplistic model, how about (suggestion) just looking at the two centres of lift and mass. Assume the centre of mass is stable (or calculated when in harbour and after being loaded) and the centre of lift wanders around it depending on whatever dynamic aspects one needs. That way you only have a lever between the two centres and a resulting vector. You only have to take into account the righting force from the angle and the distance between the two centres.

But you don't need the balls any more. Don't forget to model a dampening effect.

 

Edit: btw. modelling flight is easier 😉

I used the wrong terms. Pls. replace lift with displacement. I didn't mean aerodynamic lift on the sails, but the force that counters the weight of the boat immersed in water. Sorry for being incorrect. Still, the suggestion might be worth thinking over ... ?

Edited by Green_Baron

Share this post


Link to post
Share on other sites
On 7/9/2019 at 4:35 AM, alvaro said:

Why do you need the green spheres? Can you not calculate the buoyant force precisely, computing the water pressure at each face?

You sure can 

 

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

GameDev.net is your game development community. Create an account for your GameDev Portfolio and participate in the largest developer community in the games industry.

Sign me up!