Game.Simulation.WaterUtils
Assembly: Assembly-CSharp
Namespace: Game.Simulation
Type: public static class WaterUtils
Base: System.Object
Summary:
Utility helpers for converting between world space and water surface (heightmap) space, sampling water properties (depth, height, pollution, velocity), and raycasting against the combined terrain + water surface. Methods operate on WaterSurfaceData and TerrainHeightData structures and use float2/float3 math from Unity/MATHEMATICS. These are pure/stateless static helpers intended for use by simulation and rendering code that queries water information.
Fields
- This class is a static utility type and declares no instance fields.
{{ The class provides only static methods that operate on WaterSurfaceData and TerrainHeightData. There are no stored fields inside WaterUtils itself. }}
Properties
- This class exposes no properties.
{{ All functionality is provided via static methods. Data is passed in explicitly via ref parameters (WaterSurfaceData, TerrainHeightData). }}
Constructors
- No public constructors (static class).
{{ Being a static class, WaterUtils cannot be instantiated and has no constructors to call. }}
Methods
-
public static float3 ToSurfaceSpace(ref WaterSurfaceData data, float3 worldPosition) : System.Single[3]
{{ Converts a world-space position to water surface (heightmap) space using data.offset and data.scale. Result is in the surface coordinate system used for indexing/sampling the water data (i.e., x/z correspond to sample grid, y is surface-space depth). }} -
public static Line3.Segment ToSurfaceSpace(ref WaterSurfaceData data, Line3.Segment worldLine) : Line3.Segment
{{ Converts both endpoints of a world-space segment into water surface space. Useful before doing grid traversal or raycasts in surface space. }} -
public static float3 ToWorldSpace(ref WaterSurfaceData data, float3 surfacePosition) : System.Single[3]
{{ Converts a position from surface space back to world space. Inverse of ToSurfaceSpace for float3 positions. Note: expects surfacePosition.y to be a depth/height in surface units. }} -
public static float2 ToWorldSpace(ref WaterSurfaceData data, float2 surfaceVelocity) : System.Single[2]
{{ Converts a surface-space 2D velocity to world-space velocity by dividing by the xz scale component. }} -
public static float ToWorldSpace(ref WaterSurfaceData data, float surfaceDepth) : System.Single
{{ Converts a surface-space depth to world-space depth/height (accounts for scale.y and offset.y). Used internally when producing final world depths. }} -
public static float SampleDepth(ref WaterSurfaceData data, float3 worldPosition) : System.Single
{{ Samples the water depth at the given world-space position. Internally converts the position to surface space, bilinearly samples the four surrounding depth texels (data.depths[].m_Depth), interpolates, converts to world units and clamps to >= 0. Returns water depth (not terrain height). }} -
public static float SamplePolluted(ref WaterSurfaceData data, float3 worldPosition) : System.Single
{{ Samples the 'polluted' value from the water surface at the world position. Bilinear-interpolates the m_Polluted channel from the four surrounding samples and converts to world units via ToWorldSpace (note: no max(0) clamp is applied here). }} -
public static float2 SampleVelocity(ref WaterSurfaceData data, float3 worldPosition) : System.Single[2]
{{ Samples the water velocity at the world position. Bilinearly interpolates the m_Velocity values from the four neighboring samples and converts the result to world-space velocity (via ToWorldSpace for float2). }} -
public static float SampleHeight(ref WaterSurfaceData data, ref TerrainHeightData terrainData, float3 worldPosition) : System.Single
{{ Returns combined surface height = terrain height + water depth at the given world position. Calls SampleDepth(...) and TerrainUtils.SampleHeight(...). }} -
public static float SampleHeight(ref WaterSurfaceData data, ref TerrainHeightData terrainData, float3 worldPosition, out float waterDepth) : System.Single
{{ Overload that also returns the water depth via the out parameter. waterDepth = SampleDepth(...); return = terrainHeight + waterDepth. }} -
public static void SampleHeight(ref WaterSurfaceData data, ref TerrainHeightData terrainData, float3 worldPosition, out float terrainHeight, out float waterHeight, out float waterDepth)
{{ Full output overload that returns terrain height, water height (terrain + waterDepth), and water depth separately. }} -
public static float GetSurfaceDepth(ref WaterSurfaceData data, int2 surfacePosition) : System.Single
{{ Returns the stored depth value at the integer surface grid coordinate (x,y in surface space). Clamped to >= 0. Uses data.resolution and data.depths indexing. }} -
public static float3 GetWorldPosition(ref WaterSurfaceData data, int2 surfacePosition) : System.Single[3]
{{ Builds a world-space position for the given integer surface grid coordinate: constructs a surface-space float3 with xz = surfacePosition and y = GetSurfaceDepth(...), then converts to world space via ToWorldSpace. }} -
public static float GetSampleInterval(ref WaterSurfaceData data) : System.Single
{{ Returns the minimum sample interval in world units derived from data.scale.xz (1 / scale.x and 1 / scale.z) and returns the minimum of those. Useful for spacing sample rays/iterations. }} -
public static bool Raycast(ref WaterSurfaceData waterData, ref TerrainHeightData terrainData, Line3.Segment worldLine, bool outside, out float t) : System.Boolean
{{ Performs a raycast (segment intersection) against the combined terrain+water surface. The method: - Transforms the line into heightmap/height-space and validates intersection with bounds.
- Converts the world segment into water surface space and traverses grid cells that the segment passes through.
- For each touched water cell, calls the helper RaycastCell to test the two terrain triangles + water depth to find triangle intersections.
- If an intersection is found t is returned as a normalized parameter along the original worldLine (0..1). On failure t is set to 2.0 and returns false.
-
The 'outside' flag affects cell bounds selection and clipping behavior. }}
-
private static bool RaycastCell(ref WaterSurfaceData waterData, ref TerrainHeightData terrainData, Line3.Segment localLine, int2 pos, float2 terrainToWaterSpace, int2 waterToTerrainFactor, bool outside, out float t) : System.Boolean
{{ Private helper used by Raycast. Tests a single grid cell (pos) by: - Reading the four water depth samples for the cell and four corresponding terrain heights (converted to water space).
- Building a quad surface (split into 4 triangles via cell center) representing terrain+water heights.
- Intersecting the localLine against the cell bounds and each triangle; returns the smallest intersection t if any.
- On no intersection returns false. }}
Usage Example
// Example: sampling water height and depth at a world position
float3 worldPos = new float3(120f, 0f, 240f);
float waterDepth;
float waterHeight = WaterUtils.SampleHeight(ref waterSurfaceData, ref terrainData, worldPos, out waterDepth);
// waterDepth is the water column above terrain; waterHeight is terrain + waterDepth
// Example: getting velocity at world position
float2 worldVelocity = WaterUtils.SampleVelocity(ref waterSurfaceData, worldPos);
// Example: converting a world point to surface space and back
float3 surfacePos = WaterUtils.ToSurfaceSpace(ref waterSurfaceData, worldPos);
float3 backToWorld = WaterUtils.ToWorldSpace(ref waterSurfaceData, surfacePos);
// Example: raycast against terrain+water
Line3.Segment seg = new Line3.Segment(rayOrigin, rayOrigin + rayDirection * maxDistance);
float t;
bool hit = WaterUtils.Raycast(ref waterSurfaceData, ref terrainData, seg, outside: false, out t);
if (hit)
{
float3 hitPoint = math.lerp(seg.a, seg.b, t); // intersection position in world space
}
{{ Notes: - All sampling/conversion methods expect valid WaterSurfaceData and TerrainHeightData (scale, offset, resolution, depths/heights arrays). - Samples use bilinear interpolation and clamp to available resolution. - SampleDepth clamps negative depths to zero; SamplePolluted does not. - Raycast returns t in [0,1] when hit; on miss t is set to 2. - Methods use Unity.Mathematics for performance and can be used in performance-critical code paths. }}