evaluateAt method

({Vector3 displacement, Vector3 normal}) evaluateAt(
  1. Vector2 pos, [
  2. double? customTime
])

Evaluates exact wave displacement and surface normal at pos at current time.

Implementation

({vm.Vector3 displacement, vm.Vector3 normal}) evaluateAt(
  vm.Vector2 pos, [
  double? customTime,
]) {
  final t = customTime ?? _time;
  var disp = vm.Vector3.zero();
  var tangent = vm.Vector3(1, 0, 0);
  var binormal = vm.Vector3(0, 0, 1);

  for (final w in waves) {
    if (w.amplitude <= 0.0 || w.wavelength <= 0.0) continue;

    final k = 2 * math.pi / w.wavelength;
    final c = math.sqrt(9.81 / k);
    final phase =
        k * (w.direction.x * pos.x + w.direction.y * pos.y) -
        (w.speed * c * k) * t;
    final cosP = math.cos(phase);
    final sinP = math.sin(phase);

    final q = w.steepness / (k * w.amplitude * waves.length);

    disp.x += q * w.amplitude * w.direction.x * cosP;
    disp.y += w.amplitude * sinP;
    disp.z += q * w.amplitude * w.direction.y * cosP;

    tangent += vm.Vector3(
      -q * w.direction.x * w.direction.x * k * w.amplitude * sinP,
      w.direction.x * k * w.amplitude * cosP,
      -q * w.direction.x * w.direction.y * k * w.amplitude * sinP,
    );

    binormal += vm.Vector3(
      -q * w.direction.x * w.direction.y * k * w.amplitude * sinP,
      w.direction.y * k * w.amplitude * cosP,
      -q * w.direction.y * w.direction.y * k * w.amplitude * sinP,
    );
  }

  final norm = binormal.cross(tangent).normalized();
  return (displacement: disp, normal: norm);
}