Skip to content

Commit 77b8f48

Browse files
committed
central diffs
1 parent 10535e1 commit 77b8f48

File tree

1 file changed

+37
-4
lines changed

1 file changed

+37
-4
lines changed

content/tech/buoyancy/index.md

+37-4
Original file line numberDiff line numberDiff line change
@@ -47,8 +47,10 @@ computing the normals:
4747
on our 3D curve.
4848
* Leverage the cross product to find our normals.
4949

50-
The last one is the easiest, in my opinion. The first paragraph of [the
51-
Wikipedia article for the cross
50+
If we were to try central differences, we end up getting issues near the peak of a step curve.
51+
52+
The last one is not only the most accurate, but also the easiest, in my
53+
opinion. The first paragraph of [the Wikipedia article for the cross
5254
product](https://en.wikipedia.org/wiki/Cross_product) mentions using them to
5355
calculate normal vectors.
5456

@@ -144,8 +146,9 @@ var surface_pos = center.y
144146
This works extremely well for how simple it is, but we can take it further.
145147
Waves usually move things, right? How can we capture the force created by a
146148
wave? The amplitude of the wave should affect the strength of the push we give.
147-
It sounds like we need to look at the slope... otherwise known as the gradient
148-
which we can find using the partial derivatives of the wave.
149+
It sounds like we need to look at the slope. This means we need the derivative
150+
of our wave's function.
151+
149152
The current wave is defined by:
150153

151154
{{<katex>}}$$w\left(x,y\right)=H\cdot e^{\sin\left(\sqrt{x^{2}+y^{2}}\right)+\sin\left(y\right)}$$
@@ -216,6 +219,36 @@ wave changing slope at a given point over time, the object can eventually end
216219
up changing direction. Instead of getting stuck at some local minimum after
217220
encountering one wave, our object looks like it's swaying back and forth.
218221

222+
### Central Differences
223+
224+
While this is very precise, doing the calculus to get that gradient takes an
225+
extra step of manual work. Each time the structure of our `_wave` function
226+
changes, that new function must be differentiated. Central differences is
227+
actually viable here, making analytic differentiation unneccessary at the cost
228+
of a few extra samples. It's viable here because we take a very small step
229+
rather than reaching to the far corners of the rectangle.
230+
231+
```gdscript
232+
var step = .1
233+
var r = _wave(center + Vector3.RIGHT * step)
234+
var l = _wave(center + Vector3.LEFT * step)
235+
var u = _wave(center + Vector3.BACK * step)
236+
var d = _wave(center + Vector3.FORWARD * step)
237+
var grad = Vector3(r - l, 0.0, u - d) / (2.0 * step)
238+
```
239+
240+
Measuring the difference between this method and the last method for step sizes
241+
`.01`, `.1` and `1` were all oscillating between `0.01 and .1` using the
242+
following measurement:
243+
244+
```
245+
(grad.normalized() - _wave_gradient(center).normalized()).length()
246+
```
247+
248+
The magnitudes were massively different, with the difference in maginitude
249+
oscillating as well. This can be partially mitigated by using a higher
250+
`strength` or an extra division by `step`.
251+
219252

220253
## Swimming
221254

0 commit comments

Comments
 (0)