# 创建带有自定义模型的方块
**难度分级:☆☆**
在上一章中,我们只能创建出模型为Minecraft标准立方体的方块。然而,在很多情况下,我们希望能够自定义这些方块模型,使其视觉效果更为多样化。本章我们来实现这一目的。
## 自定义模型文件
要让方块拥有自定义模型,你需要首先为该方块准备一个模型文件。Forge为模组开发者提供了三种格式的模型文件可供选择:**Minecraft原版模型格式(.json),Blitz3D(.b3d)以及 Wavefront OBJ(.obj)**。下面将依次进行介绍。
## 使用Minecraft原版模型格式(.json)创建带有自定义模型的方块
Minecraft本身自带有一套完整的自定义模型格式规范,其文件格式和上一章所介绍的**JSON**文件格式一致。关于Minecraft原版模型格式你可以在这里找到更为详细的描述:[Minecraft Gamepedia]([https://minecraft.gamepedia.com/Model#Block\_models](https://minecraft.gamepedia.com/Model#Block_models))(需使用科学上网访问)。目前互联网上已经有相当一部分十分优秀的Minecraft原版模型建模工具,其中十分具有代表性的一款就是**BlockBench**,你可以从这里 [链接]([https://blockbench.net/downloads/](https://blockbench.net/downloads/)) 下载到其最新版本。关于建模部分本文在此不做赘述,你可以在互联网上自行查阅建模工具的使用方法。(如果是为EOK项目制作模型可以咨询GMG)
### **模型文件的设置**
使用建模工具生成的JSON文件中对于贴图路径的定义往往和项目中不同,因此你需要手动将它们指向正确的位置。首先将你的自定义模型重命名为**该物品的RegisryName.json**放进 **\\models\\block\\** 中,将该模型所用到的所有贴图放进 **\\textures\\blocks\\** 中。使用文本编辑器(Notepad++/Sublime Text等)打开JSON模型文件,它的格式类似这样:
~~~
{
"credit": "Made with Blockbench",
"textures": {
"0": "某贴图位置",
"particle": "某贴图位置"
},
"elements": [
...
],
...
}
~~~
注意到 **"textures"** 中的贴图位置和模组中应有的格式不匹配,因此你需要手动将它们重定向到你**的贴图所在位置**,他们的格式如下:
~~~
"textures": {
"贴图编号0": "你的模组modid:blocks/该模型使用到的0号贴图",
"贴图编号1": "你的模组modid:blocks/该模型使用到的1号贴图",
...
"particle": "你的模组modid:blocks/该模型粒子效果使用到的贴图"
}
~~~
修改完成后,就可以保存关闭了。
### **碰撞箱(Bounding Box)**
碰撞箱是Minecraft用来描述**实体/方块占用空间多少**的一个概念,在游戏中表现为一个**矩形的空间**。在游戏中,你可以通过快捷键**F3+B**看到每个实体的碰撞箱。当游戏检测到玩家面前有一个碰撞箱时,便会**阻挡玩家向着碰撞箱方向运动**。由于自定义模型的大小可能不足一个方块,因此我们往往也希望该方块的碰撞箱能够恰好匹配模型大小。
首先你需要在自定义方块类中新建一个由**坐标描述的碰撞箱变量(Axis Aligned Bounding Box,在代码中的类型名为AxisAlignedBB)**,它的定义方式如下:
~~~
//x1,y1,z1,x2,y2,z2均为double类型
public static final AxisAlignedBB 变量名 = new AxisAlignedBB(x1, y1, z1, x2, y2, z2);
~~~
。该类型的构造函数需要我们传入一组**矩形空间的对角线坐标**,即**描述碰撞箱体积的坐标参数**。在Minecraft世界中,**每一个方块空间**都可以抽象描述为一个以 **(0,0,0)** 和 **(1,1,1)** 为对角线端点的**矩形空间**,如下图所示:
![](https://img.kancloud.cn/a7/3f/a73f3fcb4b8da4120753da6b7aff0683_642x519.png)
因此,定义该变量的构造函数中的 **(x1,y1,z1)** 和 **(x2,y2,z2)** 分别代表该碰撞箱矩形在**每一格内部**的**对角线起始点和终止点** **(xi,yi,zi>0,i∈{1,2})**。由于Minecraft自身坐标轴的单位长度为**1/16(即0.0625D)**,因此你的每一个坐标值也必须是**0.0625D的倍数**。如果你的自定义模型超过一格,你也可以让**终点坐标大于1**。
例如在EOK中,对**双筒真空泵(Two Barrel Vacuum Pump)** 的碰撞箱 **(长1宽1高2)** 定义即为:
~~~
public static final AxisAlignedBB TWO_BARREL_VACUUM_PUMP_AABB = new AxisAlignedBB(0.0D, 0.0D, 0.0D, 1.0D, 2.0D, 1.0D);
~~~
随后你需要将该碰撞箱变量与方块绑定。你可以通过直接**覆写**Block父类中的 **getBoundingBox()** 函数来做到这一点。例如EOK双筒真空泵方块类中的代码:
~~~
public class BlockTwoBarrelVacuumPump extends Block implements IHasModel {
...
@Override
public AxisAlignedBB getBoundingBox(IBlockState state, IBlockAccess source, BlockPos pos) {
return TWO_BARREL_VACUUM_PUMP_AABB;
}
}
~~~
### **一些细节问题**
现在你的自定义模型方块已基本完成,不过还有一些细节问题需要处理。首先我们需要**覆写**Block父类中的两个函数:**isOpaqueCube()(是否为透视方块)** 和**isFullCube()(是否为完整方块)**。对于前者,除非为某些十分特殊的方块(如透视方块(**作弊警告!**)),请将它的返回值设置为**false**,否则会出现**地形透视**的渲染问题。对于后者,只要我们的模型不是一个**完整的1x1x1**的方块,就请将它的返回值设置为**false**。例如EOK双筒真空泵方块类中的相关代码如下:
~~~
public class BlockTwoBarrelVacuumPump extends Block implements IHasModel {
...
@Override
public boolean isOpaqueCube(IBlockState state) {
return false;
}
@Override
public boolean isFullCube(IBlockState state) {
return false;
}
}
~~~
随后,如果你的材质中含有**半透明/透明材质**,你还需要覆写Block父类中的 **getBlockLayer()** 函数。该函数只能在**客户端**上运行,因此你需要在函数前加上 **@SideOnly(Side.CLIENT)** 的注解。该函数的返回值是一种叫做**BlockRenderLayer**的Minecraft自带类型。其中**BlockRenderLayer.CUTOUT_MIPPED**为类似树叶这样**材质仅覆盖方块的一部分**的方块,**BlockRenderLayer.CUTOUT**为材质中**有光线可以透过部分**的方块,**BlockRenderLayer.TRANSLUCENT**为材质中有 **半透明部分(光线可以透过一部分)** 的方块。例如EOK双筒真空泵方块类中的相关代码如下:
~~~
public class BlockTwoBarrelVacuumPump extends Block implements IHasModel {
...
@SideOnly(Side.CLIENT)
public BlockRenderLayer getBlockLayer()
{
return BlockRenderLayer.TRANSLUCENT;
}
...
}
~~~
## 使用Blitz3D(.b3d)或 Wavefront OBJ(.obj)创建带有自定义模型的方块
//待补全
- 0.引子
- 基础篇 - 1.构建开发环境
- 基础篇 - 2.主类和代理
- 基础篇 - 3.创建一个物品
- 基础篇 - 4.创建一个方块
- 基础篇 - 4.1自定义方块模型
- 基础篇 - 5.初探事件系统
- 基础篇 - 6.Capability系统
- 基础篇 - 7.创建一个方块实体
- 基础篇 - 8.你的第一个GUI
- 基础篇 - 9.网络与通讯
- 进阶篇 - 0.更复杂的Mod
- 进阶篇 - 1.Minecraft渲染原理
- 进阶篇 - 2.更复杂的GUI
- 进阶篇 - 3.物品进阶
- 高级篇 - 1.深入探索OpenGL
- 高级篇 - 1.1OpenGL颜色渲染
- 高级篇 - 1.2OpenGL光照系统
- 高级篇 - 2.Minecraft贴图加载原理