Don't know why I decided to write a post now, m.b. because those liquid optimization problems are driving me crazy and I want to take a break.
So basically what I'm trying to do is to optimize liquid physics so that it would take much less cpu. Right now for a pretty huge amount of water (~8500 particles) it takes ~45% cpu (of physics thread, i.e. ~45% of 1 cpu core). That's just the water, there will be more stuff in the level, so that's unacceptable, besides, I want to have much more water and have a lot of interaction with it, like I want to have m.b. ~50-80K particles. There're several ways I want to go:
1) Move physics particle calculation to separate thread. That's not a simple thing, but possible, but still, this won't let me have my 50K-80K particle count
2) Optimizing physics particles themselves by freezing inactive particles which are deep within a large volume. That's in some way similar to physics's engine "sleeping" of inactive bodies, i.e. physics bodies can sleep until something comes in contact with them (or they're acted upon with a force)
So I've started with 2) First thing I did is this:
i.e. I split all particles into 3 layers: inner (blue), border (red) and outer (white)
* inner particles are completely inactive, they're deeper within a volume, they don't recalculate state, don't update position, etc. they're very cheap, they cost almost nothing
* border particles don't move, but they participate in collisions
* outer particles are the usual liquid particles that do all stuff
So the point here is that inner particles can become outer and outer can become inner only through border particles, thus, whenever white border around a volume gets thinner, border gets thinner and more particles are activated and vice versa, when more volume is added to the liquid the center of the volume "cools down", becomes inactive. This is not 100% complete still, since the "inner" part is no longer active it no longer applies buoyant forces to the bodies within the water, this has to be implemented separately (fairly simple actually, like finding hull and apply forces within it manually).
Making even this seemingly simple mechanic work took quite some effort, but it gained some nice speed up, about 2x. Well, I expected more, but still...
And then I started to profile more and noticed that most of the remaining "white" particles are eating cpu mostly on contacts with static bodies (the water container itself). So then I realized that it should be possible to extend the "blue" inner zone up to contact points, so that almost all water volume is inactive and only surface of the water is active. And whenever static bodies are removed the contacts are destroyed and contacting particles can become "red" and the old logic kicks off from here and everything will work fine like the liquid will pour out correctly even in this case. Implementing this turned out to be much harder, here's current state of this:
(Coloring is pretty much the same, but green points are particles that are in contact with static fixtures)
Like there're lots of problems here:
* It's very hard to "blend" the inner/border particles into the contact particle fast and right in general case, my current algorithm that I've came up with is based on dynamic programming, it's fast, but it still has some inaccuracies on borders, need to solve that somehow...
* Particles tend to form highly dense partitions near the borders, so when they unfreeze they apply large impulses to their neighbors causing them to "jump up"
* "holes" in the liquid, no idea how that happens for now...
* liquid can sometimes "crawl out" of the container from the sides
* other stuff...
But the thing is, all these optimizations together give a huge speedup, like now it only takes ~5% of cpu instead of ~45%. If I also move this to separate thread and m.b. increase particle size I can have a huge water world with all the liquid interactions I want in any place I want. What is needed to be done now is solving this pile of bugs, which is not that simple at all
But 5%, only 5% of cpu now, damn I need to make it work...