More Wave Sim
I've had a little less time the last couple weeks, but at least reached a moment where I wanted to write up an update.
Recapping where I was at:
I was really struggling to visualize dynamic waves in the game. How can I visualize the wave while being able to rotate and pan the camera? How can this be performant? The the number of points to viz and deal with is way beyond anything I've done so far.
Initially I was going to try to use C to do try to scale up how many points I could rotate, for the sake of vetting what my max potential is. Can I rotate 1000's of points in C while only being able to handle 100+ in lua?
After talking in discord (thanks @freds72) decided to rethink my approach.
Latest approach
Recapping the main goals:
- Render a grid of points
- Be able to calculate the "wave height" for each point
- Visualize each point, based on the height, to give the feeling of wave.
- Have this work for ~infinite map ( in practice I could constrain this but the idea is to have waves everywhere the jetski can travel)
I shifted to operating on the grid in AABB "world" coordinates, and thinking about mapping those back to the rotated & translated game coordinates. The idea would be to calculate which points are in view in AABB, and then viz only on those points, translating back to game coordinates.
I started in on a grouping/tile system in world coordinates - rather than computing if every point is in view, compute if a section is in view and render just that section.
I quickly realized I (sort of) already solved this problem with my background tiling approach - I could compute a grid of points for each background tile, and just keep track of the world coordinates along the way.
The end result:
- On each tick, compute a grid of offsets that is aligned on the current rotation that covers a single background tile.
- For each background tile that I render - visualize each of the offset points (calculate the height & render something).
This meant zero (0) new rotations! The offset math is all addition and subtraction. The offsets grid itself can be computed once each tick and applied to each background tile. My background algo already ensures I have a ~min set of tiles to render. I am technically rendering a little extra off camera but, marginal.
Pulling that all together... for the first time I have a wave viz that actually operates correctly in the world:
I am using slightly overlapping circles at scaled dither pattern to represent height. My compound sine wave pieces have a time element so the waves "move" while remaining still. The viz is stable as I rotate and move the world.
The bad news - this runs at about 7 fps on the device. That's a whole lot better than 0.
Honestly... I am not 100% sure I can get this within budget.
If I run the entire simulation maths but do not render any circles, I only get back to 11 fps.
I think that's sort of a good news/bad news situation. The good news is that rendering is not actually my bottle neck, so if I can optimize the math, there's hope. The bad news is - I gotta find a way to tune the math.
Two trains of thought for next steps irt tuning the maths:
- Try to precompute the wave heights
I am calculating a "height" for every x
, y
, and time
value - injecting those into a little compound sine wave formula.
I could probably modulus the x, y, and precompute, and make those lookups quite fast. The big issue here is time
- the height for any given x, y is constantly changing. I think I'd have to try to settle on looping time interval - eg there's 10 time values that I loop through. Now I can precompute every x, y for each of the the 10 ticks. Getting all that to look smooth will be tricky and finicky - it also introduces another tiling problem which might actually be hard to solve. And finally, I image it being hard to change - if I want a level with less/more waves.
- Squeeze out as much as I can in C
Return to trying out C interop and at least push the compound sine function into C, and see where that gets me. I could also try to push the entire viz into C as well - rendering the grid per background tile is pretty well isolated from all other happenings in the game, I might be able to carve it all out - but lots to learn for me on the C interop so might take a little while. The upside is keeping the smooth experience.
Bonus GIF - decided to try to make the viz good, everything the same as a above just some small tuning: