Liquid Blobs with Voxelized Marching Cubes in Minecraft

Dávid Komorowicz
Nov 5, 2014 · 5 min read
Image for post
Image for post

Nowadays every good tech/magic mod needs a form of liquid storage. As a result they look and behave very similarly. Our mod (Crafting Pillars) is visually driven, hence I wanted to re-invent the way a Liquid Tank looks in-game while retaining the same functionality.

The Idea

Inspiration came from Portal 2 which I was playing at the time. The gels floating in the air form blobs which connect and get separated as they move relative to each other. This fitted the theme perfectly: an ancient, science fiction mod, building from stone but with technology that can compress even liquids.

Image for post
Image for post
Gel from Portal 2

To fit this into the world of Minecraft however, I had to make some changes. Minecraft is made up of Cubes and round objects are usually not welcomed.


These liquid blobs are called metaballs and I will explain how they work.

We usually use an analogy from physics so that’s what I’m going to do. (Don’t worry, learn physics instead😉)

Imagine placing electrical charges into space. They will be at the center of our blobs. Now we have to compute the electric field strength at every point in our space.

To get the surface of the metaballs, we must choose a threshold value. We want our surface to contain every point in space where the field strength is equal to our threshold. (this is called an isosurface).

Mathematically speaking

Image for post
Image for post

where m is the number of charges/blobs,

Image for post
Image for post

computes the strength of the i-th charge at the location (x, y, z) and threshold is an arbitrary value we choose.

The strength of a charge is inversely proportional to the square of the distance. In other words it decreases as we move further away.

Image for post
Image for post

where (xi, yi, zi) is the position of the i-th charge

Hint: It might be interesting to play around with this function and see how the surface changes. Also try out a few different threshold values and see what works best.

Notice, that as the charges get closer together they start to connect and then completely merge as shown in image [1].

Marching Cubes Algorithm

Now that we have the equation for our surface we have to somehow display it.

In computer graphics we usually don’t render every point of a surface, but rather approximate it with triangles. Furthermore we don’t render the inside of objects, only the surface.

We divide our space into cubes along a grid and only calculate the field strengths at the grid points. We then search for the surface the following way.

For each grid cell we check if the surface is going through it. The idea is to check the corner vertices whether they are on the opposite side of the surface. For example if one vertex is inside the surface and an adjacent vertex is outside, we know that the surface must cut the edge between these two vertices so we put some triangles there.

The original algorithm is using a look up table for each way the surface can intersect with our grid cell.

Image for post
Image for post
Look Up Table for Marching Cubes

Our case is much simpler though so I won’t go into more details. There is a very good explanation here with visual illustrations.

Voxelized Algorithm

We want the surface to always align to the grid (Axis Aligned), making a nice minecraft-y look.

I created a Blobs class to store the location, strength and velocity of the charges and functions to calculate the field strength.

Next comes rendering.

First we iterate through each grid point and check if it is inside a blob. If it is we may have to render the side of the blob. Imagine being at the centre of the blob, the neighbouring cells are still inside so we don’t need sides there. If we need to render a side we simply render a quad from 2 triangles.

Here is the simplified code from the TileEntityRenderer:

Tessellator tess = Tessellator.getInstance(); VertexBuffer buffer = tess.getBuffer(); buffer.setTranslation(x, y, z); buffer.begin(GL11.GL_QUADS, DefaultVertexFormats.POSITION_TEX); final float THRESHOLD = 1; float[][][] field = Blobs.fieldStrength(te.getBlobs()); for (int i = 0; i < 16; i++) for (int j = 0; j < 16; j++) for (int k = 0; k < 16; k++) if (field[i][j][k] >= THRESHOLD) { // Cell is in the blob if (j == 15 || field[i][j + 1][k] < THRESHOLD) { // neighbour is outside (or at space bound


As a last step we need to animate the blobs. I store a list of blobs in the TileEntity class of the Tank.

In every tick/update I call the update function in the Blobs class for every charge.

This checks if a charge (centre of a blob) is colliding with the sides of our space. We will simulate perfectly elastic collisions, so we just need to multiply the respective velocity coordinate with -1.

After that we update the position of the charge with its speed.

Here are the code snippets together:

Final Words

That’s it, you’ve made it through!

I hope you found this useful and learnt something.

Originally published at on November 5, 2014.


Tech related stuff, mainly Machine Learning and VR

Medium is an open platform where 170 million readers come to find insightful and dynamic thinking. Here, expert and undiscovered voices alike dive into the heart of any topic and bring new ideas to the surface. Learn more

Follow the writers, publications, and topics that matter to you, and you’ll see them on your homepage and in your inbox. Explore

If you have a story to tell, knowledge to share, or a perspective to offer — welcome home. It’s easy and free to post your thinking on any topic. Write on Medium

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store