程序式几何体

在 Godot 中,有许多方法可以通过程序生成几何体。在本系列教程中,我们将探讨其中的几种方法。每种技术都有自己的优点和缺点,所以最好了解每种技术,以及它在特定情况下如何发挥作用。

备注

这里描述的所有程序几何生成( procedural geometry generation )方法都在 CPU 上运行。 Godot 尚不支持在 GPU 上生成几何体。

什么是几何体?

几何体是形状的一种花式说法。在计算机图形学中,几何体通常由称为“顶点”的位置数组来表示。在 Godot 中,几何体用 Mesh(网格)来表示。

什么是网格?

Godot 中很多东西的名称里都有“Mesh”:MeshArrayMeshImmediateMeshMeshInstance3DMultiMeshMultiMeshInstance3D。虽然它们都相关,但用途略有不同。

Mesh 和 ArrayMesh 是使用 MeshInstance3D 节点绘制的资源。像 Mesh 和 ArrayMesh 这样的资源不能直接添加到场景中。MeshInstance3D 代表的是某个网格在场景中的实例。你可以在多个 MeshInstance3D 中重复使用同一个网格,用不同的材质或变换(缩放、旋转、位置等)在场景的不同部分绘制它。

如果你要多次绘制同一个对象,那么将 MultiMesh 与 MultiMeshInstance3D 结合使用会很有帮助。MultiMeshInstance3D 可以以非常低的性能成本绘制数千次网格,利用的是硬件实例化的优势。使用 MultiMeshInstance3D 的缺点是所有网格的表面都只能使用同一种材质。它使用一个实例数组为每个实例存储不同的颜色和变换,但所有实例的表面使用的都是相同的材质。

什么是网格

网格(Mesh)由一个或多个表面(Surface)组成。表面是由多个子数组组成的数组,包含顶点、法线、UV 等。通常情况下,构造表面和网格的过程对用户来说是隐藏在 RenderingServer 中的,但是通过 ArrayMesh,用户可以通过传递一个包含表面信息的数组来手动构造网格。

表面

每个表面都有自己的材质。使用 MeshInstance3D 时,你也可以使用 material_override 属性来覆盖 Mesh 中所有表面的材质。

表面数组

表面数组是一个长度为 ArrayMesh.ARRAY_MAX 的数组。数组中的每个位置都填充了一个包含每个顶点信息的子数组。例如,位于 ArrayMesh.ARRAY_NORMAL 处的数组是一个顶点法线的 PackedVector3Array。有关更多信息,请参阅 Mesh.ArrayType

表面数组可以是有索引的,也可以是非索引的。创建非索引数组就像在索引 ArrayMesh.ARRAY_INDEX 处不分配数组一样简单。非索引数组为每个三角形存储唯一的顶点信息,也就是说,当两个三角形共用一个顶点时,顶点在数组中是重复的。有索引的曲面数组只存储每个唯一顶点的顶点信息,然后还存储一个索引数组,它映射出如何从顶点数组构造三角形。一般来说,使用索引数组的速度更快,但这意味着你必须在三角形之间共享顶点数据,这并不总是需要的(例如,当你想要每面法线时)。

工具

Godot 提供了不同的访问和处理几何体的方法. 关于每种方法的更多信息将在下面的教程中提供.

ArrayMesh

ArrayMesh 资源扩展了 Mesh,增加了一些不同的便捷函数,最重要的是,可以通过脚本构建 Mesh 表面。

有关ArrayMesh的更多信息,请参阅 ArrayMesh tutorial.

MeshDataTool

MeshDataTool是一个将Mesh数据转换为顶点,面和边的数组的资源,可以在运行时进行修改.

有关 MeshDataTool 的完整列表,请参见 MeshDataTool tutorial.

SurfaceTool

SurfaceTool允许使用OpenGL 1.x即时模式风格的接口创建网格.

有关SurfaceTool的更多信息,请阅读 SurfaceTool tutorial.

ImmediateMesh

ImmediateMesh 是使用立即模式风格的接口绘制对象的网格(像 SurfaceTool 一样)。ImmediateMesh 和 SurfaceTool 的区别在于,ImmediateMesh 是直接用代码动态绘制的,而 SurfaceTool 则是用来生成一个 Mesh,你可以用它做任何你想做的事。

ImmediateMesh 因为其直接的 API 而对原型设计很有用,但它的速度很慢,因为每次进行修改时都要重建几何体。它最有用的是快速添加简单的几何体来进行可视化调试(例如,通过绘制线条来可视化物理光线投射等)。

有关 ImmediateMesh的更多信息,请参见 ImmediateMesh 教程

我应该使用哪一个?

用哪种方法取决于你想做什么,以及你觉得什么样的做法用起来更舒服。

SurfaceTool和ArrayMesh都是生成不随时间变化的静态几何体(网格)的绝佳工具.

使用 ArrayMesh 比使用 SurfaceTool 稍快一些,但 API 的难度更大一些。另外,SurfaceTool 还有一些便捷的方法,比如 generate_normals()index()

ImmediateMesh 比 ArrayMesh 和 SurfaceTool 受到更多限制。但是,如果你本来就需要每一帧都改变几何体,它提供的接口更简单,甚至可能比每一帧生成一个 ArrayMesh 更快。

MeshDataTool 的速度并不快,但它可以让你访问网格的各种属性,而这些属性是其他工具无法获得的(边、面等)。当你需要根据这类数据来变换网格时,它是非常有用的,但如果不需要这些信息,就不适合使用。如果你要使用需要访问面数组或边数组的算法,最好使用 MeshDataTool。