• 论坛

导航

  • 主页
  • 样式指南
  • 入门
    • 概述
    • Mod的结构
    • Forge更新检查器
    • 依赖管理
    • 调试分析器
  • 概念
    • Sides
    • 资源
    • 注册表
    • Jar签名
    • 国际化和本地化
  • 方块
    • 概述
    • 介绍方块状态
    • 方块互动
  • 动画 API
    • 概述
    • 骨骼
    • 动画状态机
    • 使用API
  • TileEntity
    • 概述
    • 特殊渲染器
  • 物品
    • 主页
    • 战利品表
  • 模型
    • 模型概述
    • 模型文件
    • 方块状态
      • 方块状态JSON概述
      • Forge方块状态JSON
    • 绑定模型到方块和物品
    • 彩色纹理
    • 物品属性概述
    • 高级模型(未翻译)
      • 高级模型介绍
      • IModel
      • IModelState and IModelPart
      • IBakedModel
      • Extended Blockstates
      • Perspective
      • ItemOverrideList
      • ICustomModelLoader
  • 渲染
    • TileEntityItemStackRenderer
  • 事件
    • 基本用法
  • 网络
    • 主页
    • 概述
    • SimpleImpl
    • 实体
  • 数据储存
    • 能力系统
    • World Saved Data
    • 拓展实体属性
    • Config注解
  • 工具
    • 合成
    • 矿物词典
    • 权限API
  • 效果
    • 音效
  • 惯例
    • 版本命名
    • 文件位置
    • 加载阶段
  • 参与Forge开发
    • 入门
    • PR指南

高级模型介绍

尽管简单的模型和方块状态很好,但他们不是动态的。例如,Forge的通用桶可以装各种mod添加的液体。它有动态的模型,基于基础桶模型和液体。它是怎么做的呢?让我们进入IModel。

为了理解这是如何工作的,让我们看看内部的模型系统。在本节中,您可能需要参考此内容来清楚地了解正在发生的事情。反过来也是如此。 你可能不会理解这里发生的一切,但是当你浏览这一部分时,你应该能够掌握越来越多的内容,直到一切都清楚。

重要

如果你是第一次通读,请不要跳过_任何东西_!为了有全面的理解,你_必须_读所有的东西!同样,如果这是您第一次阅读,请不用在意页面上的链接,因为那是更深层次的东西。

  1. 通过ModelLoader加载用ModelResourceLocation标记的模型集合

    • 对于物品,他们的模型必须手动标记由ModelLoader.registerItemVariants加载(用ModelLoader.setCustomModelResourceLocation)完成。

    • 对于方块,它由状态映射得到一个Map<IBlockState, ModelResourceLocation>。迭代所有的方块,然后映射中的所有值会被加载。

  2. IModel由每个ModelResourceLocation加载,并缓存至一个Map<ModelResourceLocation, IModel>。

    • IModel仅由ICustomModelLoader加载得到。(多个加载器尝试加载一个模型会报LoaderException)。如果没有找到模型,并且ResourceLocation实际上是一个ModelResourceLocation(也就是,它不是一个普通的模型,而是一个方块状态的变体),那么他会调用方块状态加载器(VariantLoader)。否则的话,该模型是一个正常的原版JSON模型,它会用原版的方式加载(VanillaLoader)。

    • 一个原版JSON模型(models/item/*.json 或 models/block/*.json)加载后,它是一个ModelBlock(即使它是物品)。这是一个原版的类,与IModel无关。为了纠正它,它被包装到一个VanillaModelWrapper里,VanillaModelWrapper实现了IModel。

    • 一个原版/Forge的方块变体加载时,先加载它的完整的方块状态JSON。这个JSON解析到一个ModelBlockDefinition里,那里面缓存着JSON的路径。然后变体定义的列表由ModelBlockDefinition导出到WeightedRandomModel。

    • 当加载一个原版JSON物品模型 (models/item/*.json)时,模型需要一个带有变体名inventory的ModelResourceLocation(例如,泥土方块物品的模型是minecraft:dirt#inventory);从而导致模型由VariantLoader加载(尽管它是ModelResourceLocation),若VariantLoader加载失败了,则再用VanillaLoader。

      • 最重要的副作用是,如果VariantLoader加载出错,它会尝试用VanillaLoader加载。如果这也出错了,它会导致两个stacktrace。第一个是VanillaLoader的,第二个是VariantLoader的。当调试模型错误时,分析正确的stacktrace很重要。
    • 一个IModel可由ResourceLocation加载或通过调用ModelLoaderRegistry.getModel从缓存中检索或做为其中一个异常处理备选方案。

  3. 加载的模型的所有材质依赖会被加载,并放入材质集。材质集是一个巨大的材质,它把所有模型材质粘贴在一起。当模型要渲染一个材质时,它会加上额外的UV偏移,来匹配材质集中材质的坐标。

  4. 每个模型调用model.bake(model.getDefaultState(), ...)来贴图。返回值IBakedModel会被缓存进一个Map<ModelResourceLocation, IBakedModel>。

  5. 此映射(map)然后被存入ModelManager。ModelManager是一个存在Minecraft::modelManager里的单例,它是私有的,没有getter。

    • ModelManager可以不通过反射或访问转换获得,通过Minecraft.getMinecraft().getRenderItem().getItemModelMesher().getModelManager() 或 Minecraft.getMinecraft().getBlockRenderDispatcher().getBlockModelShapes().getModelManager()。与它们的名字相反,它们是一样的。

    • 可以用ModelManager的ModelManager::getModel从缓存中获取一个IBakedModel(没有加载或/贴图的模型,仅获取已有的缓存)

  6. 最后,IBakedModel会渲染。这是由IBakedModel::getQuads完成的。它的返回值是BakedQuad的列表(quadrilaterals: 四边形)。然后它们可以传递给GPU渲染。物品和方块在这里有所不同,但它逻辑相对简单。

    • 原版物品有属性和重载。为了实现它,IBakedModel定义了getOverrides,它返回一个ItemOverrideList。ItemOverrideList定义了handleItemState,它里面有原始的模型、实体、世界和栈,来找到最终的模型。重载在模型其它所有操作之前完成,包括getQuads。因为IBlockState不适用于物品,当渲染物品时,IBakedModel::getQuads的state参数接受null值。

    • 方块有方块状态,当一个方块的IBakedModel被渲染时,IBlockState直接传入getQuads方法。仅在模型的上下文中,方块状态可以有额外的属性,参考unlisted properties。

基于 MkDocs 使用自定义主题构建. 托管于 Read the Docs.
启用夜间模式