Example Minecraft Worlds Created with FME

Evie L
Evie L
  • Updated

Introduction

Mojang Minecraft can be used to visualize data using FME. In the How to article How to Make Minecraft Worlds, we walked through building a Minecraft world from scratch using FME. In this article, we highlight key features for creating worlds from different datasets. You can download all workspaces and completed worlds from the Files section in this article.

image.png

FME is an excellent tool for bringing real data of any kind into Minecraft. Vector layers, rasters, point clouds, and 3D models can be transformed, adjusted, and aligned to the required size and position in the Minecraft world.

In FME, a Minecraft world is a regularly spaced point cloud, so the transformation task is essentially combining all necessary sources into such a cloud. Below we go through several examples that show different techniques of making Minecraft worlds.

Files

Additional files are available on the right-hand side of this article.

LAS Example

Surprisingly, "normal" (i.e., irregularly spaced) point clouds aren't that good for direct Minecraft writing. If a point cloud's density isn't high enough for the chosen resolution, the writer will produce an output with holes in the surface that go to the bottom of the world, and we definitely don't want Steve to fall through them.

A possible solution that creates a smooth continuous surface is rasterization of the point clouds (and other features if necessary - see the Bowen Island example) and converting them into a point cloud again. The following example takes a LAS dataset downloaded using the Norwegian Mapping Authority demo web service.

Since the source point cloud contains ground and vegetation classes (class 2 and class 5, respectively), we can split it and process each part separately.

The ground points will serve as a source for the RasterDEMGenerator. We will also use them to make a vector outline of the island (HullReplacer). This will clip the generated raster to the island's shape, so the rest can be filled with water.

With the vegetation point cloud, we perform a similar operation to get the vector areas that represent forest. After clipping the island with the forest, we get open areas, where we will plant flowers.

At this stage, we transform everything into point clouds and set components (PointCloudCombiner and PointCloudExpressionEvaluator,​​​​​​​or PointCloudComponentAdder, respectively). We also need to add the elevations to the point cloud made from forest areas. For that, we round up the X and Y coordinates of both the point cloud made from the DEM and the point cloud made from the forest polygons, and use the PointCloudMerger to transfer the Z component to the forest points.

Again, one more important step when dealing with vegetation is adding a block type that supports vegetation under all plants. Because we are writing to version 1.7, the types are "Grass" (blockID = 2), "Dirt" (blockID = 3, blockData = 0 or 1), and "Podzol" (blockID = 3, blockData = 2). In our workflow, we covered all island surfaces with Grass blocks, so we only have to elevate all trees and flowers by one block with the PointCloudExpressionEvaluator (@Component(z)+1).

In this workflow, we use a natural way of growing trees: we plant saplings (blockID = 6) of different kinds (blockData is randomly generated between 0 and 5), and they slowly grow into adult trees of different sizes and shapes.

We also need to randomly thin the forest point clouds because we don't want to plant a tree on every block - that would make a really dense, impassable forest. Unfortunately, FME does not have a random number generator within PointCloudExpressionEvaluator. Instead, we use an expression that produces a more-or-less random result while calculating a number between 0 and 9. The trees will be planted on the blocks where the result of the expression is equal to 1:

@floor(@sin((@Component(x))*@Component(y)/1000-@floor(@sin(@Component(x))*@Component(y)/1000))*10)==1

Similar expressions generate tree and flower types.

When we open the world for the first time, the scene looks as follows:

image.png

After one Minecraft day, which is about 20 minutes long, the landscape changes to this:

image.png

As we can see, many trees have grown in 24 Minecraft hours. Closer inspection also reveals all kinds of animals - as well as other, not always friendly, creatures.

Vector Example

The abundance of vector data today suggests it will be one of the most popular data sources for making Minecraft worlds. In this example, we will use several vector layers and a single raster DEM.

Bowen Island is a small and beautiful island near Vancouver. For this island, we have elevation data as a raster in CDED format, Esri shapefiles of hydrography and roads, and forest polygons in MapInfo TAB.

image.png

In this example, we will rasterize all vector layers before creating the final point cloud. FME is a perfect tool for manipulating rasters and turning them into point clouds. This is why the rasterization approach can be quite useful in many situations.

Here is how it works: each pixel in the raster entering the PointCloudCombiner becomes a point. Band 0 is used for setting the elevation of each point; color bands, if present, will become color components; all other bands are also turned into components; and if the bands have names, they will be used as component names. So, for example, if band 1 was called blockID and band 2 was called blockData, they would become blockID and blockData components, respectively.

Before rasterization, we perform some operations on vector data. We buffer all linear features: residential and collector roads, and streams. Then we use all the buffers for clipping the island so there are no overlapping polygons in the dataset. These steps ensure that when we create a single point cloud, each feature has enough space and doesn't "fight" for the same location.

In this workspace, we assign the blockID and blockData attributes through a custom transformer called the MinecraftStyler. It lists all the block types available in Minecraft, making it easier to pick the right block. It also lets you add a vertical offset, which may be needed for some blocks such as vegetation, as we already know.

Another custom transformer rasterizes incoming features and builds the point cloud. The 3DForcer and NumericRasterizers make separate rasters for blockID, blockData, and vertical offset. As you can see, we are not limited to the bands that eventually will be used by the Minecraft writer - we can have as many intermediate auxiliary bands as we need. The RasterExpressionEvaluators let you combine all the rasters into a single image, where Band 0 is reserved for Z, Band 1 is blockID, Band 2 is blockData, and Band 3 is _vertical_offset. In the image, we assign the band names and turn everything into a point cloud. The PointCloudOnRasterComponentSetter allows transferring the Z value from the DEM to the points.

Here is the output of the translation:

image.png

For comparison, here is how the same area looks in Google Earth:

image.png

BIM Example

Minecraft can serve as a simple, interactive viewer for BIM data. We can easily transform an IFC or Revit model into a Minecraft world and go for a walk around and inside the building, climb up the stairs, look out the window, then spread our wings and take to the sky.

image.png

Railway Example

We already know about the blocks that require some additional processing for proper functioning - e.g., vegetation blocks need certain types of blocks placed below them. Some blocks need to know how to connect to similar blocks adjacent to them - for example, stairs, fences, rails, and many others.

image.png

In this example, we will convert Vancouver Skytrain (the light rail system) data from an Esri Shapefile to Minecraft. If we simply take Skytrain lines and turn them into rail blocks, none will know how to connect to their neighbors, and all rails will run North to South even if the line runs East to West. This is caused by the difference between "normal" block placement in Minecraft, where blocks "get acquainted" with their surroundings and can make an educated decision about proper placement, and writing all blocks at once.

The rail block's orientation is coded with the blockData component to determine the direction first, then set the blockData accordingly with a long conditional statement.

image.png

To find how to properly orient each rail block, we take the following steps. First, we replace the smooth feature with rounded, zigzag-like lines, chop the zigzag into single points, and build squares from each point. Then, with the SpatialRelator, we analyze where the neighbors for each square are - we check the existence of the neighbors on the North and South sides as well as to the East and West sides. Based on that, and using a complicated condition, we create an attribute:

image.png

Finally, we replace the squares with points, which can be turned into the final point cloud. The illustration below shows how the original line changes during the transformation:

image.png

You can place rails on slopes in a similar way, although it requires much more analysis.

Rail crossings can be difficult to deal with in FME. Once the world is created, it makes sense to check and correct them manually. See the Minecraft Wiki for more details.

The output is a world with some railways:

image.png

Maze Example

This simple workspace creates a world with two identical mazes. It is a game within a game - in multiplayer mode, the participants can try to beat each other in finding the quickest way from the entrance to the exit.

A short Python script generates the maze as text, and a few transformers turn the text into glass walls in the Minecraft world. Let the racers enter the world, and then - ready, set, go!

image.png

Additional Resources

Data Attribution

Data used in this tutorial originates from data made at Safe Software, Metro Vancouver, the City of Vancouver Open Data Portal, and the Norwegian Mapping Authority. It contains information licensed under the Open Government License.

Was this article helpful?

We're sorry to hear that.

Please tell us why.

As of January 14th, 2026, comments on knowledge base articles have been closed. To make sure questions don’t get missed and to enable more community support, we’ve moved discussions to the FME Community. If you have a question or a comment about this article, please create a new post or create a support ticket.