pub struct OceanParams {
pub windspeedms: f64,
pub winddirection: [f64; 2],
pub fetchkm: f64,
pub depthm: f64,
pub gridsize: u32,
pub patchsizem: f64,
pub gravity: f64,
}
impl Default for OceanParams {
fn default() -> Self {
Self {
windspeedms: 10.0,
winddirection: [1.0, 0.0],
fetchkm: 500.0,
depthm: 4000.0,
gridsize: 256,
patchsizem: 1000.0,
gravity: *crate::SURFACEGRAVITY,
}
}
}
pub struct OceanSpectrum {
pub heights: Vec<f64>,
pub normals: Vec<[f64; 3]>,
pub gridsize: u32,
}
impl OceanParams {
pub fn phillipsspectrum(&self, kx: f64, ky: f64) -> f64 {
let ksq = kx * kx + ky * ky;
if ksq < 1e-12 {
return 0.0;
}
let k = ksq.sqrt();
let l = self.windspeedms * self.windspeedms / self.gravity;
let kdotw = (kx * self.winddirection[0] + ky * self.winddirection[1]) / k;
let damping = 0.001;
let phillips = ((-1.0 / (k * l).powi(2)).exp() / ksq.powi(2))
* kdotw.powi(2)
* (-ksq * damping * damping).exp();
phillips.max(0.0)
}
pub fn generatespectrum(&self) -> OceanSpectrum {
let n = self.gridsize as usize;
let mut heights = vec![0.0; n * n];
let normals = vec![[0.0, 1.0, 0.0]; n * n];
for j in 0..n {
for i in 0..n {
let kx =
(2.0 * std::f64::consts::PI * (i as f64 - n as f64 / 2.0)) / self.patchsizem;
let ky =
(2.0 * std::f64::consts::PI * (j as f64 - n as f64 / 2.0)) / self.patchsizem;
heights[j * n + i] = self.phillipsspectrum(kx, ky).sqrt();
}
}
OceanSpectrum {
heights,
normals,
gridsize: self.gridsize,
}
}
pub fn dispersion(&self, k: f64) -> f64 {
(self.gravity * k * (k * self.depthm).tanh()).sqrt()
}
}