this is a giveaway more than a tutorial!
so again i found a great tutorial on fluid simulation using a method called smoothed particle hydrodynamics (sph) which is a method to simulate fluids, smoke …etc
quantumyeti.com is for sale | HugeDomains (it’s a three part tutorial)
i ported the c# tutorial to cocos2d-x c++ with some of my tweaks and here it is after working on it for a while … runs at 60fps on win32. i never got a chance to try it on mobile but it should work with a small number of particles like 600 or so:
what i changed from the c# tutorial is the hash map plus i added fluid vs dynamic body interactions
also the tutorial used box2d for the physics but i used cocos integrated physics which is based on chipmunk2d
i used my own crafted hash map for this to work as the std::unordered_map gave terrible performance
the hash map is inspired from this stackoverflow post (look at 'Tony Delroy'
answer):
for the rendering am using no shaders at all just a threshold shader
any physics body you want it to interact with the fluids use ParticlesManager::addPhysicsBody
and the body has to be a PolygonBody
dont use too many particles in a tight container or you will have pressure problems but in any case if you do then you should comment this line in ParticlesManager::calculateForce()
float pressure = (particle.p - 5.f) / 2.0f;
and replace it with this line
float pressure = 0.4f * (particle.p - 5.f) / 2.0f;
hashmap properties needs a bit of explaining especially MaxMapSize
MaxBucketSize
depends on CellSize
MaxMapSize
no matter what has to be greater or equal to MAX_PARTICLES
another thing that need to be careful about is the hashing function which is the getkey()
method that maps a 2d grid coord (x, y) to a 1d array indices
there are two implementations of this method that you could choose from
now the difference between the two is that the first is faster but not safe meaning not any map size will work which means you need to experiment and for me if i choose this implementation then i tend to make the size a multiplier of 1024 but be careful because when i tried 1024 * 5 for some reason it didn’t work but other numbers worked like: 1024, 1024 * 2, 1024 * 3, 1024 * 4, 1024 * 6
the second is a bit slow but any map size you choose will work
a word of advice don’t tamper too much with the hashmap properties
Good References:
As3 Spatial Hash (if you don’t know what a Spatial Hash is)
GitHub - mdellavo/boourns: JBox2D Demo (jbox2d demo)
GitHub - omgware/fluid-simulator-v2: Fluid Simulator implementing all the main algorithms like SPH, MPM and PBF (another java port … look at FluidSimulatorLiquid.java)
GitHub - jingquanalex/FluidEngine2D: 2D SPH fluid simulation (good clean c# sph port)
Intel | Data Center Solutions, IoT, and PC Innovation (good sph article read)
http://www.box2d.org/forum/viewtopic.php?f=3&t=574&start=70 (fluid vs dynamic body interactions inspired from here)
Chipmunk2D/Buoyancy.c at master · slembcke/Chipmunk2D · GitHub (Buoyancy from here)
for better understanding of Buoyancy
update 1:
i modified the fragment shader so you can easily enable/disable borders now
just open up the fragment shader file frag.fsh and uncomment or comment this line to enable or disable fluid border:
#define EnableFluidBorder
update 2:
you can now grab fluid particles and toss them around!!!
emitter and add boxes has to be turned off first.
PS: frame dips in the video are do to recording.
here is the source code between your hands. do with it what you like!
cocos2d-x fluids.zip (14.4 KB)