Blender  V2.93
ocean_spectrum.c
Go to the documentation of this file.
1 /*
2  * This program is free software; you can redistribute it and/or
3  * modify it under the terms of the GNU General Public License
4  * as published by the Free Software Foundation; either version 2
5  * of the License, or (at your option) any later version.
6  *
7  * This program is distributed in the hope that it will be useful,
8  * but WITHOUT ANY WARRANTY; without even the implied warranty of
9  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10  * GNU General Public License for more details.
11  *
12  * You should have received a copy of the GNU General Public License
13  * along with this program; if not, write to the Free Software Foundation,
14  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
15  */
16 
21 #include "BKE_ocean.h"
22 #include "BLI_math.h"
23 #include "ocean_intern.h"
24 
25 #ifdef WITH_OCEANSIM
26 
27 /* -------------------------------------------------------------------- */
31 /*
32  * Original code from EncinoWaves project Copyright (c) 2015 Christopher Jon Horvath
33  * Modifications made to work within blender.
34  *
35  * Licensed under the Apache License, Version 2.0 (the "License");
36  * you may not use this file except in compliance with the License.
37  * You may obtain a copy of the License at
38  *
39  * http://www.apache.org/licenses/LICENSE-2.0
40  */
41 
46 static float alpha_beta_spectrum(const float alpha,
47  const float beta,
48  const float gamma,
49  const float omega,
50  const float peakomega)
51 {
52  return (alpha * sqrt(gamma) / pow(omega, 5.0)) * exp(-beta * pow(peakomega / omega, 4.0));
53 }
54 
55 static float peak_sharpen(const float omega, const float m_peakomega, const float m_gamma)
56 {
57  const float peak_sharpening_sigma = (omega < m_peakomega) ? 0.07 : 0.09;
58  const float peak_sharpening = pow(
59  m_gamma, exp(-sqrt((omega - m_peakomega) / (peak_sharpening_sigma * m_peakomega)) / 2.0));
60 
61  return peak_sharpening;
62 }
63 
67 static float ocean_spectrum_wind_and_damp(const Ocean *oc,
68  const float kx,
69  const float kz,
70  const float val)
71 {
72  const float k2 = kx * kx + kz * kz;
73  const float k_mag_inv = 1.0f / k2;
74  const float k_dot_w = (kx * k_mag_inv * oc->_wx) + (kz * k_mag_inv * oc->_wz);
75 
76  /* Bias towards wind dir. */
77  float newval = val * pow(fabs(k_dot_w), oc->_wind_alignment);
78 
79  /* Eliminate wavelengths smaller than cutoff. */
80  /* val *= exp(-k2 * m_cutoff); */
81 
82  /* Reduce reflected waves. */
83  if (k_dot_w < 0.0f) {
84  if (oc->_wind_alignment > 0.0) {
85  newval *= oc->_damp_reflections;
86  }
87  }
88 
89  return newval;
90 }
91 
92 static float jonswap(const Ocean *oc, const float k2)
93 {
94  /* Get our basic JONSWAP value from #alpha_beta_spectrum. */
95  const float k_mag = sqrt(k2);
96 
97  const float m_omega = GRAVITY * k_mag * tanh(k_mag * oc->_depth);
98  const float omega = sqrt(m_omega);
99 
100  const float m_fetch = oc->_fetch_jonswap;
101 
102  /* Strictly, this should be a random value from a Gaussian (mean 3.3, variance 0.67),
103  * clamped 1.0 to 6.0. */
104  float m_gamma = oc->_sharpen_peak_jonswap;
105  if (m_gamma < 1.0) {
106  m_gamma = 1.00;
107  }
108  if (m_gamma > 6.0) {
109  m_gamma = 6.0;
110  }
111 
112  const float m_windspeed = oc->_V;
113 
114  const float m_dimensionlessFetch = fabs(GRAVITY * m_fetch / sqrt(m_windspeed));
115  const float m_alpha = 0.076 * pow(m_dimensionlessFetch, -0.22);
116 
117  const float m_tau = M_PI * 2;
118  const float m_peakomega = m_tau * 3.5 * fabs(GRAVITY / oc->_V) *
119  pow(m_dimensionlessFetch, -0.33);
120 
121  const float beta = 1.25f;
122 
123  float val = alpha_beta_spectrum(m_alpha, beta, GRAVITY, omega, m_peakomega);
124 
125  /* Peak sharpening */
126  val *= peak_sharpen(m_omega, m_peakomega, m_gamma);
127 
128  return val;
129 }
130 
136 float BLI_ocean_spectrum_piersonmoskowitz(const Ocean *oc, const float kx, const float kz)
137 {
138  const float k2 = kx * kx + kz * kz;
139 
140  if (k2 == 0.0f) {
141  /* No DC component. */
142  return 0.0f;
143  }
144 
145  /* Get Pierson-Moskowitz value from #alpha_beta_spectrum. */
146  const float peak_omega_PM = 0.87f * GRAVITY / oc->_V;
147 
148  const float k_mag = sqrt(k2);
149  const float m_omega = GRAVITY * k_mag * tanh(k_mag * oc->_depth);
150 
151  const float omega = sqrt(m_omega);
152  const float alpha = 0.0081f;
153  const float beta = 1.291f;
154 
155  float val = alpha_beta_spectrum(alpha, beta, GRAVITY, omega, peak_omega_PM);
156 
157  val = ocean_spectrum_wind_and_damp(oc, kx, kz, val);
158 
159  return val;
160 }
161 
166 float BLI_ocean_spectrum_texelmarsenarsloe(const Ocean *oc, const float kx, const float kz)
167 {
168  const float k2 = kx * kx + kz * kz;
169 
170  if (k2 == 0.0f) {
171  /* No DC component. */
172  return 0.0f;
173  }
174 
175  float val = jonswap(oc, k2);
176 
177  val = ocean_spectrum_wind_and_damp(oc, kx, kz, val);
178 
179  /* TMA modifications to JONSWAP. */
180  const float m_depth = oc->_depth;
181  const float gain = sqrt(m_depth / GRAVITY);
182 
183  const float k_mag = sqrt(k2);
184 
185  const float m_omega = GRAVITY * k_mag * tanh(k_mag * oc->_depth);
186  const float omega = sqrt(m_omega);
187 
188  const float kitaigorodskiiDepth_wh = omega * gain;
189  const float kitaigorodskiiDepth = 0.5 + (0.5 * tanh(1.8 * (kitaigorodskiiDepth_wh - 1.125)));
190 
191  val *= kitaigorodskiiDepth;
192 
193  val = ocean_spectrum_wind_and_damp(oc, kx, kz, val);
194 
195  return val;
196 }
197 
206 float BLI_ocean_spectrum_jonswap(const Ocean *oc, const float kx, const float kz)
207 {
208  const float k2 = kx * kx + kz * kz;
209 
210  if (k2 == 0.0f) {
211  /* No DC component. */
212  return 0.0f;
213  }
214 
215  float val = jonswap(oc, k2);
216 
217  val = ocean_spectrum_wind_and_damp(oc, kx, kz, val);
218 
219  return val;
220 }
221 
224 #endif /* WITH_OCEANSIM */
float BLI_ocean_spectrum_texelmarsenarsloe(const struct Ocean *oc, const float kx, const float kz)
float BLI_ocean_spectrum_piersonmoskowitz(const struct Ocean *oc, const float kx, const float kz)
float BLI_ocean_spectrum_jonswap(const struct Ocean *oc, const float kx, const float kz)
sqrt(x)+1/max(0
#define M_PI
Definition: BLI_math_base.h:38
btVector3 m_depth
static CCL_NAMESPACE_BEGIN const double alpha
INLINE Rall1d< T, V, S > pow(const Rall1d< T, V, S > &arg, double m)
Definition: rall1d.h:359
INLINE Rall1d< T, V, S > tanh(const Rall1d< T, V, S > &arg)
Definition: rall1d.h:422
INLINE Rall1d< T, V, S > exp(const Rall1d< T, V, S > &arg)
Definition: rall1d.h:295
ccl_device_inline float beta(float x, float y)
Definition: util_math.h:666
ccl_device_inline float2 fabs(const float2 &a)