Skip to content

Commit 8b66306

Browse files
committed
update random stuff
1 parent 2df5596 commit 8b66306

File tree

5 files changed

+94
-67
lines changed

5 files changed

+94
-67
lines changed

content/tech/buoyancy/foam.png

169 KB
Loading

content/tech/buoyancy/index.md

+61-48
Original file line numberDiff line numberDiff line change
@@ -6,19 +6,21 @@ weight: 920
66

77
{{<video "demo.webm" >}}
88

9-
For the intro to a game I (perodically) work on, I decided to put the player on
10-
a pirate ship. Scrolling textures on a big plane looked pretty boring. To make
11-
things a bit angrier I decided to add waves.
9+
During the intro to a game I (perodically) work on, the player starts on a
10+
pirate ship. Realistic water doesn't fit the style, and scroling textures on a
11+
big plane looked pretty boring. To make things a bit angrier I needed intense
12+
waves, and I needed those waved to actually affect the world.
1213

1314
## Waves
1415

15-
The visual component is the most common technique for basic waves: displacing
16-
the height of each vertex on a subdivided plane.
16+
To keep it simple, we'll just do a procedural heightmap; i.e. set the vertical coorinate to
17+
be a function of the horizontal position and time.
1718

18-
Inspired by [sum of sines](https://developer.nvidia.com/gpugems/gpugems/part-i-natural-effects/chapter-1-effective-water-simulation-physical-models#:~:text=The%20sum%20of%20sines%20gives,to%20the%20continuous%20water%20surface.)
19-
which can make semi-realistic ocean shaders, I'm taking the basic idea of adding two waves
20-
with different frequencies to break up the repetitiveness. The result is good enough for this
21-
cartoon style.
19+
[Sum of
20+
sines](https://developer.nvidia.com/gpugems/gpugems/part-i-natural-effects/chapter-1-effective-water-simulation-physical-models#:~:text=The%20sum%20of%20sines%20gives,to%20the%20continuous%20water%20surface.)
21+
can add some semi-realistic texture to the surface of the water. I'm not doing
22+
that, but I am taking the basic idea of adding two waves with different
23+
frequencies to break up the repetitiveness.
2224

2325

2426
```glsl
@@ -38,16 +40,20 @@ void vertex() {
3840

3941
## Floating
4042

41-
There are two components to making objects float on top of our waves:
43+
The fun part is making the waves interactive. There are two components to
44+
making objects float on top of our waves:
4245

4346
* Position: move the object up and down so it sits on top of the water.
4447
* Rotation: orient the object according to the slope of the waves.
4548

4649
We generally want some of the object to sit beneath the surface of the water.
47-
Instead of doing anything fancy like using volume to calculate actual buoyancy,
48-
we can just define our own y-offset from the model's postition, and a 2D size
49-
of the "buoyancy-plane". In Godot, `CSGBox3D` conveiently lets us visualize and edit
50-
these properties.
50+
There are more realistic buoyancy simulations that figure out the displacement according
51+
to the amount of a volume that sits beneath the surface. The complexity and noise that
52+
comes with an accurate solution doesn't fit the style, so instead we're going to fit a plane to
53+
the waves surface.
54+
55+
It's easy to adjust the plane within the Godot editor, without doing anything
56+
custom, by defining a CSGBox3D that is thrown away at runtime.
5157

5258
![CSGBox3D as a buoyancy plane](boundingplane.png)
5359

@@ -85,27 +91,26 @@ because I assume the shape of my rectangle is longer on that axis.
8591

8692
```gdscript
8793
# find the corners (the rotation puts us into global space, needed by _wave)
88-
var front_r = center + (Vector3(size.x, 0, size.y) / 2.0).rotated(Vector3.UP, plane.global_rotation.y)
89-
var front_l = center + (Vector3(-size.x, 0, size.y) / 2.0).rotated(Vector3.UP, plane.global_rotation.y)
90-
var back_r = center + (Vector3(size.x, 0, -size.y) / 2.0).rotated(Vector3.UP, plane.global_rotation.y)
91-
var back_l = center + (Vector3(-size.x, 0, -size.y) / 2.0).rotated(Vector3.UP, plane.global_rotation.y)
92-
93-
# project the points onto the wave
94-
front_r.y = _wave(front_r)
95-
front_l.y = _wave(front_l)
96-
back_l.y = _wave(back_l)
97-
back_r.y = _wave(back_r)
94+
# Define corners in local space
95+
var local_corners = [
96+
Vector3( half_x, 0, half_z), Vector3(-half_x, 0, half_z), # front
97+
Vector3(-half_x, 0, -half_z), Vector3( half_x, 0, -half_z), # back
98+
]
99+
100+
# Rotate and add to center (global space), then apply wave
101+
for i in range(local_corners.size()):
102+
local_corners[i] = center + local_corners[i].rotated(Vector3.UP, rot_y)
103+
local_corners[i].y = _wave(local_corners[i])
104+
105+
# Also project center on the wave
98106
center.y = _wave(center)
99107
100-
# average normals from the triangles
101-
var normal_f = (front_l - center).cross(front_r - center).normalized();
102-
var normal_b = (back_r - center).cross(back_l - center).normalized();
103-
108+
# Compute the two triangle normals
109+
var normal_f = (local_corners[1] - center).cross(local_corners[0] - center).normalized()
110+
var normal_b = (local_corners[3] - center).cross(local_corners[2] - center).normalized()
104111
105-
# rotation based on avg of cross products of triangles in the plane
106-
var normal = ((normal_b + normal_f) / 2.0)
107-
# undo the global space transformation
108-
normal = normal.rotated(Vector3.UP, -plane.global_rotation.y).normalized()
112+
# Average the normals, then undo the global space rotation
113+
var normal = ((normal_f + normal_b) * 0.5).rotated(Vector3.UP, -rot_y).normalized()
109114
```
110115

111116
{{< gallery >}}
@@ -117,23 +122,27 @@ normal = normal.rotated(Vector3.UP, -plane.global_rotation.y).normalized()
117122
From left to right are examples using the back normal, the averaged normals and
118123
the front normal on top of a sharp peak.
119124

125+
To be scientific about it, I plotted a "smoothness" field, the gradient of the computed
126+
normal-field. Not very surprising, sampling a bigger area results in smoother changes.
127+
The cross-product approach had the lowest variance, and spreads the variance around a larger
128+
space.
129+
130+
![smoothness graph](smooth_field.png)
131+
120132
### Position
121133

122-
Assuming our buoyancy-plane is already offset from the model, and we use
123-
`position.y = wave(position.xy)`, concave parts of the curve will have the boat
124-
dip into the water on each side.
134+
A naive `position.y = wave(position.xy)` means that at concave parts of the curve,
135+
our plane will undernath the surface.
125136

126137
{{< gallery >}}
127138
<img src="finite_diffs_width.png" class="grid-w50"/>
128139
<img src="adjust_pos.png" class="grid-w50"/>
129140
{{< /gallery >}}
130141

131-
We should re-frame our goal to be none of the or extremes of our bounding shape
132-
dip under the water. If we instead use the mean of our samples, we fix the concave case but now we'll
133-
end up submerged in convex areas.
134-
135-
To get the best of both, we just take the `max` of the center sample or the edge
136-
samples ([desmos](https://www.desmos.com/calculator/y4neofo1zw)).
142+
If we instead use the mean of our samples, we fix the concave case but now
143+
we'll end up submerged in convex areas. To get the best of both, we just take
144+
the `max` of the center sample or the edge samples' mean
145+
([desmos](https://www.desmos.com/calculator/y4neofo1zw)).
137146

138147
```gdscript
139148
# for central differences, re-use the samples
@@ -240,11 +249,15 @@ parent.velocity.y = impulse.y
240249

241250
{{<video "swim.webm" >}}
242251

243-
## Conclusion
252+
## What's next
253+
254+
* Make some levels with this!
255+
* Swimming/water levels. Diving?
256+
* Make it so you can drive the ship.
257+
* Taking advantage of the waves to gain some height could be a game mechanic.
258+
* A better surface shader, that uses depth and a bit of transparency.
259+
* ~~Foam.~~ I made foam!
260+
261+
262+
![foam](foam.png)
244263

245-
Both the game's frame-budget and my own free time to work on personal projects
246-
are limited. It might be fun to implement a proper plane fitting algorithm such
247-
as [Least Squares](https://en.wikipedia.org/wiki/Least_squares) or [Principal
248-
Component
249-
Analysis](https://en.wikipedia.org/wiki/Principal_component_analysis), but the
250-
added fidelity (and noise) aren't worth the effort for this style of game.
143 KB
Loading

content/tech/chinese_app/index.md

+26-11
Original file line numberDiff line numberDiff line change
@@ -172,10 +172,11 @@ quite a work in progress. Currently you can import content from:
172172

173173
Major TODOs are:
174174

175-
* Allow saving stories to be read later
175+
* ~~Allow saving stories to be read later~~ Done!
176176
* An editor mode that allows writing and editing content directly.
177-
* A button that shows other potential words in the dictionary if my automated
178-
mappings are wrong.
177+
* ~~A button that shows other potential words in the dictionary if my automated
178+
mappings are wrong~~. Done!
179+
* ~~Custom TextPainter and Markdown support~~ Done!
179180
* Potentially, a curated library of content. I'm not sure how I'd source this
180181
legally and ethically. Unless...
181182
* Users or teachers could produce and share their own content, potentially
@@ -350,17 +351,31 @@ would be fun to one day play in a competition overseas in Taiwan or mainland
350351
China. Besides the daily review, you can also do a cutom review and filter
351352
using these tags if you're studying a particular topic.
352353

353-
## Conclusion
354-
354+
## What's next?
355355

356356
{{< gallery >}}
357357
<img src="pics/stats.png" alt="tag on words" class="grid-w100">
358358
{{< /gallery >}}
359+
359360
The main idea of the app is "bring your own content". I've been dogfooding
360361
it for a little while now, and it has definitely sped up my vocab acquisition.
361-
I'm not sure whether the long term plan is to polish it and publish it as FOSS,
362-
or to make it a closed source side-hustle.
363-
364-
In the meantime, I'll continue to iterate. It's a slow going process and I
365-
just have the nights and weekends that I'm not doing other hobbies like BJJ or
366-
Yu-Gi-Oh. I'm happy with the progress I've made so far.
362+
There is a lot of polish yet to be done. Scalabilty checks, testing on other devices,
363+
and just a couple more features:
364+
365+
* A screen reader to get the tap-to-lookup experience in any app. Likely
366+
Android only.
367+
* Curated content library. Maybe even daily/weekly releases of short readers,
368+
like [Maayot](https://www.maayot.com/).
369+
* Reccomendation algorithms to asses a new user's current Chinese level, and
370+
371+
* Test the pinyin model, and potentially train an additional model, to ensure
372+
traditional chinese works well.
373+
* Integrate a higher quality dictionary. CEDIT is pretty good, but I at least need
374+
to have the option to hide "Potentially innapropriate words". For example,
375+
reading about [a duck (鸭) shouldn't show a slang definition "male prostitute" by
376+
default.
377+
](https://www.mdbg.net/chinese/dictionary?page=worddict&email=&wdrst=0&wdqb=%E9%B8%AD)
378+
379+
I'm not sure when it will be done.I'll continue to iterate. It's a slow going
380+
process and I just have the nights and weekends that I'm not doing other
381+
hobbies and work. Hopefully I can make this project a priority in the near future.

content/tech/triplanar/index.md

+7-8
Original file line numberDiff line numberDiff line change
@@ -17,9 +17,9 @@ I want to use heightmaps to add details without extra geometry. The concern is
1717
mostly on my workflow, not on performance. I'm simply too lazy to model that into
1818
my modules in a tileable way.
1919

20-
The effect is turned up a bit to make it extra apparent int he sample. The floor
21-
shouldn't be offset so strongly if you want to have a character walk on it without
22-
them appearing to levitate.
20+
The effect is turned up a bit to make it extra apparent int the images here.
21+
The floor shouldn't be offset so strongly if you want to have a character walk
22+
on it without them appearing to levitate.
2323

2424
## Heightmap with Deep Parallax
2525

@@ -36,11 +36,10 @@ tutorial, and I think the results are just fine.
3636

3737
## The Shader
3838

39-
Here's the code for those who are interested. It's mostly me gluing code from
40-
various tutorials together. Also there's some unnessary conditionals I have for
41-
toggling the ability to use two sets of textures for the walls and floor. In
42-
reality there should be a separate shader for each, or some preprocessor stuff
43-
instead of a runtime check.
39+
It's mostly gluing code from various tutorials together. Also there's some
40+
unnessary conditionals I have for toggling the ability to use two sets of
41+
textures for the walls and floor. In reality there should be a separate shader
42+
for each, or some preprocessor stuff instead of a runtime check.
4443

4544
```c
4645
shader_type spatial;

0 commit comments

Comments
 (0)