Sunday, January 3, 2016

Fluid Simulation using BabylonJS and LiquidFun

BabylonJS and LiquidFun allow for the creation of fluid simulations including soft body physics, using JavaScript and WebGL!



Creating the Physics Sim

Like all physics engines, the first step for using LiquidFun is to create a World.

        // Liquid Fun Physics objects
        var gravity = new b2Vec2(0, -10);
        world = new b2World(gravity);

To create water and soft body physics using LiquidFun, we use Particle Groups. In the example below, we are creating a "rectangle" that will be filled with liquid particles. 

        // water
        var shape = new b2PolygonShape();
        var vertices = shape.vertices;
        vertices.push(new b2Vec2(-5, -1));
        vertices.push(new b2Vec2(5, -1));
        vertices.push(new b2Vec2(5, -2));
        vertices.push(new b2Vec2(-5, -2));
        var pd = new b2ParticleGroupDef();
        pd.shape = shape;
        pd.color.Set(0, 0, 192, 255);
        var group = particleSystem.CreateParticleGroup(pd);

Creating a soft body (like jelly) is just as easy - we just need to set a couple of extra flags in the particle group definition:

        // red jelly circle
        var circle = new b2CircleShape();
        circle.position.Set(-1, 8);
        circle.radius = 0.5;
        var pgd = new b2ParticleGroupDef();
        pgd.flags = b2_elasticParticle;
        pgd.groupFlags = b2_solidParticleGroup;
        pgd.shape = circle;
        pgd.color.Set(192, 0, 0, 255);

Drawing using BabylonJS

There are two different types of items we need to draw in BabylonJS: particles and bodies. BabylonJS has a robust particle system which allows customization through a custom update function. Inside this custom update function, we can set the Babylon particle position and color based on the LiquidFun particle information:

        // draw particle systems
        for (var i = 0, max = world.particleSystems.length; i < max; i++) {
            var system = world.particleSystems[i];

            var particles = system.GetPositionBuffer();
            var color = system.GetColorBuffer();
            var maxParticles = particles.length;
            var transform = new b2Transform();

            for (var i = 0, c = 0;
     i < maxParticles && i < particlesBJS.length; 
                 i += 2, c += 4) {
                particlesBJS[i].position.x = particles[i];
                particlesBJS[i].position.y = particles[i + 1];
                particlesBJS[i].color.r = color[c];
                particlesBJS[i].color.g = color[c + 1];
                particlesBJS[i].color.b = color[c + 2];
Drawing the other bodies, such as ground or rigid physics objects is usually dependent on what you want to show in your simulation. In the demo,  we have ground objects and a little "smiley face" mesh that can be dragged around. In the case of the "smiley face," I used a cylinder with a material for the face:

var shape = BABYLON.Mesh.CreateCylinder("cylinder", 0.1, fixture.shape.radius * 2, fixture.shape.radius * 2, 24, 1, that._scene, false); 

... and then updating the position of the objects must be done on each iteration of the render loop. We need to set the position of the BabylonJS objects to be the same as the LiquidFun physics bodies:

var pos = fixture.body.GetPosition();
var angle = fixture.body.GetAngle();
fixture.babylonShape.position.x = pos.x;
fixture.babylonShape.position.y = pos.y;

Next Steps

This was just a quick overview of using BabylonJS and LiquidFun together. If you want to learn more, here are some links to get started: