Using WaveFront OBJ Models for Blocks

This is an advanced tutorial and you need to know the basics of Tile Entity Special Renderers, as well as Tile Entities.

I will be adding a snowball block with a custom model.

To start, you need your block as a tile entity. I won’t be covering how to do this exactly in this tutorial, but my block and tile entity code is as follows:

public class BlockSnowball extends BlockContainer
{
    private static final String name = "snowball";

    public BlockSnowball()
    {
        super(Material.snow);
        setBlockTextureName(Tutorial.MODID + ":" + name);
        setBlockBounds(0.25F, 0, 0.25F, 0.75F, 0.5F, 0.75F);
        setBlockName(name);
        GameRegistry.registerBlock(this, name);
    }
    @Override
    public boolean shouldSideBeRendered(IBlockAccess world, int x, int y, int z, int side)
    {
        return false;
    }

    @Override
    public boolean isOpaqueCube()
    {
        return false;
    }

    @Override
    public boolean renderAsNormalBlock()
    {
        return false;
    }

    @Override
    public TileEntity createNewTileEntity(World world, int par2)
    {
        return new TESnowball();
    }
}

The setBlockTextureName() method only serves to set the icon it uses on block break particles. Other than that, it’s not needed because it will be overridden by the block model. The block bounds is adjusted to be as close as possible to your block model. The other extra boolean methods are to make sure your block renders correctly, because it is not a full block.

Now, let’s see the tile entity code.

public class TESnowball extends TileEntity
{

}

You don’t really need much, if at all, code in this class. Don’t forget to map it! It just serves to make the tile entity special renderers possible for this block. So, let’s make that. This is the most complicated part.

public class TESRSnowball extends TileEntitySpecialRenderer
{
    IModelCustom model = AdvancedModelLoader.loadModel(new ResourceLocation(PlaceableItems.MODID, "obj/snowball.obj"));
    ResourceLocation texture = new ResourceLocation(PlaceableItems.MODID, "textures/blocks/snowball.png");

    @Override
    public void renderTileEntityAt(TileEntity entity, double x, double y, double z, float p_147500_8_) {

        bindTexture(texture);

        GL11.glPushMatrix();
        GL11.glEnable(GL12.GL_RESCALE_NORMAL);
        GL11.glColor4f(1.0F, 1.0F, 1.0F, 1.0F);
        GL11.glTranslatef((float) x + 0.5F, (float) y + 0.0F, (float) z + 0.5F);
        GL11.glScalef(0.09375F, 0.09375F, 0.09375F);

        model.renderAll();
        GL11.glPopMatrix();
    }
}

That’s it, our TESR is done. You can tweak the translate and scale to your liking. You can even add rotation to that with GL11.glRotatef(rotation, amountX, amountY, amountZ). As you can see I specified the textures and the obj files on top. If you want my model file, you can get it as “snowball.obj” from a mod of mine’s resources here.

Oops, almost forgot, we also need to register our TESR to the client proxy, so the client can render it. Add this to your register renderers method:

ClientRegistry.bindTileEntitySpecialRenderer(TESnowball.class, new TESRSnowball());

We’re done! Here’s the final result:
2015-04-03_13.10.55

Leave a comment