what I worked on
Looking at a new floating mechanism. Found this great paper with Unity code:
The first one is more applicable for us. It bases the floating on the volume of mesh triangles submerged under the water, using Archimedes' principle, we calculate the volume of the object that is in the water and apply buoyancy based on that.
For each frame we check if all three vertices of a triangle are under the water, over the water, or intersecting the surface and clip the triangle accordingly. We then get the submerged volume and centroid to apply the buoyant force.
The second repo was a more realistic simulation but way slower so we're skipping that one, though I did like the aesthetic of their demo.
decisions & reasoning
The original paper assumes flat water, which isn't our case. So we translate the vertices to fluid space, each vertex moves down by the amount the wave has pushed it up, and then we compare everything against a flat plane.
The original version used the divergence theorem to calculate both the total object volume and the submerged volume, with the reference point always at the object's center. This works for flat water but breaks for non-flat surfaces. We moved the reference point to the average of the submerged XZ coordinates so it can better calculate the volume under water.
We also clip triangle edges correctly by finding the intersection point between a submerged and a non-submerged vertex using binary search.
One thing I'm considering: if the boat has a physically accurate floating simulation, will that create problems because the boat isn't actually well-designed in real life? Also, the paper and the repo both recommend using just the hull mesh rather than the full boat mesh, so I'll look into how to do that.
the hydrostatic pressure model
I also implemented an alternative model based on section 4.4 of the paper (which was left unimplemented there). Instead of computing how much water we displace, it computes the pressure the water exerts on each triangle.
We calculate the hydrostatic pressure:
where = water density (1000 kg/m³), = gravity, = depth in water. The force on a surface patch with area and normal is:
In code we use the area vector (negative because force pushes against the normal):
Vector3 triForce = -1 * fluidDensity * gravity * triDepth * areaVector;
We then split this into total upward force and total torque. The torque comes from , where is the lever arm from the center of mass. Left and right cancel when the boat is level, and if one side sits deeper it gets more force, which torques the boat back toward level.
blender
Spun up Blender for the first time to remove interior polygons from our boat model, they interfered with the algorithm since it expects a clean hull surface. Ended up going with the hull-only strategy the paper recommended anyway, so two birds one stone.
result
The boat floats like a real boat now, a lot better than with the 4-point system.
One note on the signed volume: if the total calculated volume comes out negative due to numerical noise from the vertex-shifting step, we flip the sign. It's not a bug in the algorithm, more of a numerical artifact we handle.
Settled on the pressure model in the end. Probably biased since I spent more time playing with it, but I think it's the right call, the torque behavior feels more physically grounded.