FME Version
Files
Introduction
Mojang Minecraft can be used to visualize data using FME. In the How to article How to Make Minecraft Worlds, we walked through how to build a Minecraft world from scratch using FME. In this article, we will highlight some key features for creating worlds with different datasets. All the workspaces and completed worlds can be downloaded from the Files section on this article.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.
For FME, a Minecraft world is a regularly spaced point cloud, so the transformation task is essentially a combining of all the necessary sources into such a cloud. Below we go through several examples that show different techniques of making Minecraft worlds.
Content Overview
LAS Example
Surprisingly, "normal" (i.e. irregularly spaced) point clouds aren't that good for direct Minecraft writing. If the density of a point cloud is not high enough for the chosen resolution, the writer will produce an output with holes in the surface going to the bottom of the world, and we definitely don't want Steve to fall through these holes.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 also will use them for making a vector outline of the island (HullReplacer). This will allow clipping the generated raster to the shape of the island, 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 are ready to 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 X and Y coordinates of both the point cloud made from DEM, and the point cloud made from the forest polygons, and use the PointCloudMerger to transfer the Z component to 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" (block ID = 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)==1Similar expressions are used for generating tree and flower types.
When we open the world first time, the scene looks as follows:
After one Minecraft day, which is about 20 minutes long, the landscape changes to this:
As we can see, a lot of 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
An abundance of vector data in today's world suggests that 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 in the form of a raster in CDED format, Esri Shapefiles of hydrography and roads, and forest polygons in MapInfo TAB.
In this example, we will rasterize all the vector layers before going to 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 of the raster entering the PointCloudCombiner is turned into a point. Band 0 is used for setting the elevation of each point; color bands, if present, will become color components; all other bands also are 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 guarantee that when we make a single point cloud, all features get enough space and don't "fight" for the same location.
In this workspace, we assign the blockID and blockData attribute through a custom transformer called the MinecraftStyler. It lists all the block types available in Minecraft and makes it easier to pick the right block. It also allows adding a vertical offset, which may be needed for some blocks such as vegetation, as we already know.
Another custom transformer takes care of rasterizing incoming features and making 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 allow combining 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:
For comparison, here is how the same area looks in Google Earth:
BIM Example
Minecraft can serve as a very simple and interactive viewer for BIM data. We can easily transform an IFC or Revit model to 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.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 the similar blocks adjacent to them - for example, stairs, fences, rails, and many others.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 of them will know how to connect to their neighbors, and all rails will go from North to South even if the line goes from East to West. This is caused by the difference between "normal" block placing in Minecraft, when the blocks "get acquainted" with the surroundings and can make an educated decision about their proper placement, and writing all blocks at once.
The orientation of the rail blocks is coded with the blockData component as follows to determine the direction first and then code the blockData accordingly with a long condition statement.
In order to find how to properly orient each rail block, we take the following steps. First, we replace the nice smooth feature with rounded-up zigzag-looking 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:
Finally, we replace the squares with the points, which can be turned into the final point cloud. The illustration below shows how the original line changes during the transformation:
Placing rails on the slopes can be done in a similar way, although it would require much more analysis.
Rail crossings can be difficult to deal with in FME. Once the world is created, it makes sense to manually check and correct them. See the Minecraft Wiki for more details.
The output is a world with some railways:
Maze Example
This simple workspace makes a world with two identical mazes within it. It is a game within a game - in a multiplayer mode, the participants can try to beat each other in finding the quickest way from the entrance to the exit.A short Python code generates the maze as text, and with a few transformers, the text is turned into glass walls of the Minecraft world. Let the racers enter the world, and then - ready, set, go!
Additional Resources
- MinecraftStyler Custom Transformer
- Building Norway in Minecraft with FME
- Minecraft Reader/Writer
- How To Make Minecraft Worlds
Comments
0 comments
Please sign in to leave a comment.