Skip to content

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. }}