Update 52

Garret is currently busy with moving to a new place, so I’ve used this week to do some more experimental technical work.

Probably the biggest and most important system that’s still entirely missing is the scenery visibility checking. I had done some initial tests a couple months ago though, and this week was a good opportunity to push it a bit further to figure out what we can do with it.

Here’s a debug screenshot:

Every white line here connects a path tile with the scenery items that are visible from that spot, taking occlusions into account. Of course it’s just a rough approximation, and it has only been done for the rock objects here for testing purposes, but as you can see that’s still a slightly crazy amount of calculations that need to be done.

You can imagine that it’s not a great idea to test every path tile against every single scenery item in the game world - a method for quickly getting only nearby objects relative to a given point is needed. This can be achieved using space partitioning: for example, imagine that the game world is divided into two halves, A and B, and you have done some calculations beforehand to figure out which objects are inside half A and which are inside half B. If you now want to know which objects are within a certain range of some point you first check how far away that point is from your two halves - if one of the halves is further away than the range you’re interested in, you know that all objects inside that half are outside the range as well and you don’t need to do any distance checks against them individually. Nice!

Now, instead of using just two halves a better and slightly more sophisticated approach is to use a hierarchy of ever-smaller cubes that partition space more fine-grained in areas with lots of objects. This structure is called an Octree, and it’s one of the usual solutions for doing space partitioning (see the linked Wikipedia article if you’re interested in learning more about it!).

To my own surprise we so far got away without using one, but we rarely had to do checks against nearby objects so far (e.g., for checking collisions when building something new - this is only done for one single frame, and checking against every single object in the game world was fast enough so far to not cause any overly noticeable lag).
There are so many scenery visibility checks to do though that it was necessary now, and we would have needed it for bigger parks anyways.

Here’s what an octree looks like in action:

And with that the performance of doing the visibility checks is in a feasible range now (and some older code received a performance boost too!). The main problem left is that recalculating everything when loading a park still takes too long, but before working on that we should figure out for which kinds of objects we’ll use these visibility checks anyways (probably not for every single little stone?), and how much they add to the gameplay.