Wednesday 22 April 2015

Mapping IBlockStates to IBakedModels. ISmartBlockModel.

This topic is just a few notes about how Minecraft uses IBlockStates to retrieve the corresponding IBakedModel, to help you understand the vanilla code a bit more (which is pretty complicated)

When rendering a block, the renderer needs to retrieve the correct IBakedModel for the given IBlockState of the block.  Broadly speaking, this occurs in two decoupled steps:

  1.  The IBlockState is used to look up a ModelResourceLocation using BlockStateMapper.
  2.  The ModelResourceLocation is then used to retrieve the IBakedModel using ModelManager.
After retrieving the IBakedModel, Forge checks if this is an ISmartBlockModel.  If so, it is customized using IExtendedBlockState information for the specific Block position being rendered.


Some miscellaneous notes


  1. ModelResourceLocation is a tag for the model, of the form “mymodid:granite#normal”.  By default, the ModelLoader will look for it in
    assets/mymodid/blockstates/granite.json:
    {
        "variants": {
            "normal": { "model": "granite_model" }
        }
    }
    In this example, it will create an IBakedModel from granite_model.json.
  2. It’s usually not necessary to provide an appropriate BlockStateMapping, because the default uses your block’s registered name and its properties, which are generally what you need.  If you do need a custom mapper, use ModelLoader.setCustomStatemapper().  BlockModel.registerAllBlocks() has good examples how to ignore some of a block’s properties, for example cactus model is the same for all AGE values.
  3. By default, ModelLoader registers a ModelResourceLocation for every entry in the BlockStateMapper.
  4. You can use ModelBakeEvent to insert custom models into the ModelManager; alternatively you can register an ICustomerModelLoader with ModelLoaderRegistry, which bypasses the vanilla ModelLoader for your chosen blocks– for example see B3DLoader.
  5. The ISmartBlockModel instance stored in the ModelManager is the “default”.  When called, ISmartBlockModel.handleBlockState() then returns a new instance to suit the IExtendedBlockState.  You shouldn't modify the "default" in handleBlockState because block rendering is multithreaded - you need to return a new instance, or alternatively an immutable one that you have cached,
  6. The various registries are cached and only updated when the resources are reloaded.


5 comments:

  1. Hi! I tried to replicate your SmartModel 3D Web, but IBakedModel is deprecated... Will you update this in the near future? Or should I continue doing it that way?

    Thanks in advance :)

    ReplyDelete
  2. Hi. Don't worry about the "IBakedModel is deprecated" warning, it will work fine. Rainwarrior just wants you to use IFlexibleBakedModel instead, which is totally unnecessary in most cases :)

    -TGG

    ReplyDelete
  3. Hello, TGG!

    I am building Quantum API (https://j.mp/QuantumAPI), and I am about to release a public beta. The last step before actually releasing the beta version is to get Models working.

    Long story short, I'm trying to figure out the whole rendering structure. Your tutorial explains how to do things well, but not the whole structure. What I'm looking for specifically is where Models are loaded, assembled, and used.

    The way the API currently is, you have a choice of AbsoluteModels, which are normal models that are permanently scaled to the default 16x16 resource packs, and ReflexiveModels, which scales models according to the resolution of the resource pack, so, for example, if the resolution is 32x32, a ReflexiveModel is rendered at half the size. I need to know how to make a custom renderer for Blocks, Items, Entities, etc., the current system I already understand. I just can't seem to find which method in what class that I call to add custom resources to a resource pack.

    I've noticed that IResourcePack is simply a list of IResources which contain file paths, but I don't know what uses the actual IResourcePack to load objects for use by the rendering engine. Can ya help out a fellow coder? (And is it just me or does modding minecraft suck!? Well, at least I put up with it to make this API where you'll never see minecraft code again and mods are backwards compatible, eh?)

    ReplyDelete
  4. Hi Link
    Sounds interesting, good luck I think it is an ambitious job :)
    Check out ModelLoader. That's where all the action starts. It's pretty complicated. IModel is the interface for models loaded from model files, before they are baked.
    -TGG

    ReplyDelete
  5. This comment has been removed by the author.

    ReplyDelete