使用 SurfaceTool

SurfaceTool 提供了一个用于构造几何体的有用接口。该接口类似于 ImmediateMesh 类。你设置每个顶点的属性(例如法线、uv、颜色),然后当你添加顶点时,它就会捕获这些属性。

SurfaceTool 还提供了一些有用的辅助函数,如 index()generate_normals()

属性是在添加每个顶点之前添加的:

var st = SurfaceTool.new()

st.begin(Mesh.PRIMITIVE_TRIANGLES)

st.set_normal() # Overwritten by normal below.
st.set_normal() # Added to next vertex.
st.set_color() # Added to next vertex.
st.add_vertex() # Captures normal and color above.
st.set_normal() # Normal never added to a vertex.

当使用 SurfaceTool 完成生成几何体后,调用 commit() 完成生成网格。如果将一个 ArrayMesh 传递给了 commit() ,那么它就会在这个 ArrayMesh 的末尾附加一个新的表面。而如果没有传递任何信息, commit() 则返回一个 ArrayMesh。

# Add surface to existing ArrayMesh.
st.commit(mesh)

# -- Or Alternatively --

# Create new ArrayMesh.
var mesh = st.commit()

以下代码会创建一个无索引的三角形。

var st = SurfaceTool.new()

st.begin(Mesh.PRIMITIVE_TRIANGLES)

# Prepare attributes for add_vertex.
st.set_normal(Vector3(0, 0, 1))
st.set_uv(Vector2(0, 0))
# Call last for each vertex, adds the above attributes.
st.add_vertex(Vector3(-1, -1, 0))

st.set_normal(Vector3(0, 0, 1))
st.set_uv(Vector2(0, 1))
st.add_vertex(Vector3(-1, 1, 0))

st.set_normal(Vector3(0, 0, 1))
st.set_uv(Vector2(1, 1))
st.add_vertex(Vector3(1, 1, 0))

# Commit to a mesh.
var mesh = st.commit()

你可以选择添加一个索引数组,可以通过调用 add_index() 将顶点添加到索引数组中,也可以通过调用 index() 将顶点数组缩小以删除重复的顶点.

# Suppose we have a quad defined by 6 vertices as follows
st.add_vertex(Vector3(-1, 1, 0))
st.add_vertex(Vector3(1, 1, 0))
st.add_vertex(Vector3(-1, -1, 0))

st.add_vertex(Vector3(1, 1, 0))
st.add_vertex(Vector3(1, -1, 0))
st.add_vertex(Vector3(-1, -1, 0))

# We can make the quad more efficient by using an index array and only utilizing 4 vertices:

st.add_vertex(Vector3(-1, 1, 0))
st.add_vertex(Vector3(1, 1, 0))
st.add_vertex(Vector3(-1, -1, 0))
st.add_vertex(Vector3(1, -1, 0))

# Creates a quad from four corner vertices.
# add_index() can be called before or after add_vertex()
# since it's not an attribute of a vertex itself.
st.add_index(0)
st.add_index(1)
st.add_index(2)

st.add_index(1)
st.add_index(3)
st.add_index(2)

# Alternatively we can use ``st.index()`` which will create the quad for us and remove the duplicate vertices
st.index()

同样,如果你有一个索引数组,但希望每个顶点都是唯一的(例如,因为想在每个面而不是每个顶点使用唯一的法线或颜色),可以调用 deindex() .

st.deindex()

如果你不想自行添加自定义法线,那么可以使用 generate_normals() 来添加,调用时机应该是在生成几何体之后、使用 commit()commit_to_arrays() 提交网格之前。调用 generate_normals(true) 会将最终的法线翻转。另外请注意,generate_normals() 只有在图元类型为 Mesh.PRIMITIVE_TRIANGLES 时有效。

你可能发现了,在生成的网格上,法线贴图或者其他一些材质属性看上去不对劲。这是因为对法线贴图而言,必需的是切线,这和法线是两码事。有两种解决方法,手动添加切线信息,或者使用 generate_tangents() 自动生成。这个方法要求每个顶点都已经具有 UV 和法线。

st.generate_normals()
st.generate_tangents()

st.commit(mesh)

默认情况下,生成法线时将以逐顶点为基础进行计算(即生成"平滑法线")。如果想要平面顶点法线(即每个面使用单一法向量),在添加顶点时,调用 add_smooth_group(i) . 其中 i 是每个顶点的唯一编号。 add_smooth_group() 需要在建立几何体时调用,例如在调用 add_vertex() 方法之前.