Saturday 15 February 2020

Block Shapes (VoxelShapes) [1.14.4+]



Something that’s important to understand for non-full-cube blocks is the concept of their shape.
The image that you see on the screen (when a block is rendered) is determined by the block model (i.e. the model json file).  But Minecraft also uses a number of other ‘shapes’ to control the interaction of the block with its environment and with the player. Unlike block models, which are defined using a configuration file (json), these other shapes are defined in the code for the Block class itself.
The class which describes a block’s shape is VoxelShape, which you can visualise as a 3-dimensional grid where each grid location (“voxel”) is either full or empty.  Minecraft uses code to build up the VoxelShape from 3D rectangular boxes (cuboids);

VoxelShape being built up from two components using VoxelShapes.or()



 
Creating a VoxelShape with holes using VoxelShapes.combineAndSimplify() with IBooleanFunction.ONLY_FIRST

The coordinate system for the VoxelShape is the same as for models, i.e. a 1x1x1 cubic metre block is 16 x 16 x 16.

VoxelShape coordinate system

Minecraft uses four different types of shape to characterise the block:

BlockState.getShape()

This is the “default” shape of the block.  It is the shape used to draw the outline of the block when your player is directly looking at it.  In most cases, this is the shape used for the other three types of block shapes as well.

Examples of BlockState.getShape()

BlockState.getCollisionShape()


This is the shape used to determine how players or entities “collide” with the block.  For example, the collision shape for a fence or a wall extends far above the rendered model.  Blocks with the doesNotBlockMovement() property have no collisionShape.

The BlockState.getCollisionShape() for fences and walls is higher than the block.  This stops players and entities from jumping over.

BlockState.getRenderShape()

The render shape is used for lighting and shadows purposes and for rendering shortcuts (hiding block faces which the player can’t see).  In most cases this is the same as the default shape, but for a few (Skull, Fence) it is different.  I’m not sure of the reason.


BlockState.getShape() in red, compared with BlockState.getRenderShape() which is empty.

BlockState.getRayTraceShape()

RayTrace is the name of the algorithm that Minecraft uses to determine what object the player is looking at when the player uses an item or tries to mine a block.  The algorithm determines which block the player is affecting, as well as the face of the block (east, north, up, etc) being clicked.  For a few blocks (Cauldron, Composter, Hopper, Scaffold) the RayTraceShape is used to modify the raytrace algorithm to return a different result.  I’m not sure why that’s important.

Composter BlockState.getShape() in red compared with the BlockState.getRayTraceShape() in purple.














6 comments:

  1. I wonder how do you show those different Voxel Shapes? Is it a Mod or anything else? Could you tell me plz.

    ReplyDelete
  2. Hi
    Yeah it's a simple class in a teaching / tutorial mod
    The mod source code is here
    https://github.com/TheGreyGhost/MinecraftByExample

    The relevant class is here
    https://github.com/TheGreyGhost/MinecraftByExample/blob/master/src/main/java/minecraftbyexample/usefultools/debugging/DebugBlockVoxelShapeHighlighter.java

    Cheers
    TGG

    ReplyDelete
  3. Thanks for explainining this!

    ReplyDelete
  4. thank you very much, from Vietnam

    ReplyDelete
  5. Absolute goldmine... thank you for taking the time to do this. Very much appreciated!

    ReplyDelete