void GetBuoyancyInformation(EntityCollidable collidable, out float submergedVolume, out Vector3 submergedCenter)
{
BoundingBox entityBoundingBox;
RigidTransform localTransform;
RigidTransform.TransformByInverse(ref collidable.worldTransform, ref surfaceTransform, out localTransform);
collidable.Shape.GetBoundingBox(ref localTransform, out entityBoundingBox);
if (entityBoundingBox.Min.Y > 0)
{
//Fish out of the water. Don't need to do raycast tests on objects not at the boundary.
submergedVolume = 0;
submergedCenter = collidable.worldTransform.Position;
return;
}
if (entityBoundingBox.Max.Y < 0)
{
submergedVolume = collidable.entity.volume;
submergedCenter = collidable.worldTransform.Position;
return;
}
Vector3 origin, xSpacing, zSpacing;
float perColumnArea;
GetSamplingOrigin(ref entityBoundingBox, out xSpacing, out zSpacing, out perColumnArea, out origin);
float boundingBoxHeight = entityBoundingBox.Max.Y - entityBoundingBox.Min.Y;
float maxLength = -entityBoundingBox.Min.Y;
submergedCenter = new Vector3();
submergedVolume = 0;
for (int i = 0; i < samplePointsPerDimension; i++)
{
for (int j = 0; j < samplePointsPerDimension; j++)
{
Vector3 columnVolumeCenter;
float submergedHeight;
if ((submergedHeight = GetSubmergedHeight(collidable, maxLength, boundingBoxHeight, ref origin, ref xSpacing, ref zSpacing, i, j, out columnVolumeCenter)) > 0)
{
float columnVolume = submergedHeight * perColumnArea;
Vector3.Multiply(ref columnVolumeCenter, columnVolume, out columnVolumeCenter);
Vector3.Add(ref columnVolumeCenter, ref submergedCenter, out submergedCenter);
submergedVolume += columnVolume;
}
}
}
Vector3.Divide(ref submergedCenter, submergedVolume, out submergedCenter);
//Pull the submerged center into world space before applying the force.
RigidTransform.Transform(ref submergedCenter, ref surfaceTransform, out submergedCenter);
}