float GetSubmergedHeight(EntityCollidable collidable, float maxLength, float boundingBoxHeight, ref Vector3 rayOrigin, ref Vector3 xSpacing, ref Vector3 zSpacing, int i, int j, out Vector3 volumeCenter)
{
Ray ray;
Vector3.Multiply(ref xSpacing, i, out ray.Position);
Vector3.Multiply(ref zSpacing, j, out ray.Direction);
Vector3.Add(ref ray.Position, ref ray.Direction, out ray.Position);
Vector3.Add(ref ray.Position, ref rayOrigin, out ray.Position);
ray.Direction = upVector;
//do a bottom-up raycast.
RayHit rayHit;
//Only go up to maxLength. If it's further away than maxLength, then it's above the water and it doesn't contribute anything.
if (collidable.RayCast(ray, maxLength, out rayHit))
{
//Position the ray to point from the other side.
Vector3.Multiply(ref ray.Direction, boundingBoxHeight, out ray.Direction);
Vector3.Add(ref ray.Position, ref ray.Direction, out ray.Position);
Vector3.Negate(ref upVector, out ray.Direction);
//Transform the hit into local space.
RigidTransform.TransformByInverse(ref rayHit.Location, ref surfaceTransform, out rayHit.Location);
float bottomY = rayHit.Location.Y;
float bottom = rayHit.T;
Vector3 bottomPosition = rayHit.Location;
if (collidable.RayCast(ray, boundingBoxHeight - rayHit.T, out rayHit))
{
//Transform the hit into local space.
RigidTransform.TransformByInverse(ref rayHit.Location, ref surfaceTransform, out rayHit.Location);
Vector3.Add(ref rayHit.Location, ref bottomPosition, out volumeCenter);
Vector3.Multiply(ref volumeCenter, .5f, out volumeCenter);
return Math.Min(-bottomY, boundingBoxHeight - rayHit.T - bottom);
}
//This inner raycast should always hit, but just in case it doesn't due to some numerical problem, give it a graceful way out.
volumeCenter = Vector3.Zero;
return 0;
}
volumeCenter = Vector3.Zero;
return 0;
}