SurfaceToolの使用

SurfaceTool は、ジオメトリを構築するための便利なインターフェイスを提供します。このインターフェースは ImmediateMesh ノードに似ています。頂点ごとの各属性(例: normal、uv、color)を設定し、頂点を追加すると属性がキャプチャされます。

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.

When finished generating your geometry with the SurfaceTool, call commit() to finish generating the mesh. If an ArrayMesh is passed to commit(), then it appends a new surface to the end of the ArrayMesh. While if nothing is passed in, commit() returns an ArrayMesh.

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

# -- Or Alternatively --

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

The code below creates a triangle without indices.

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()

You can optionally add an index array, either by calling add_index() and adding vertices to the index array manually, or by calling index() once, which generates the index array automatically and shrinks the vertex array to remove duplicate vertices.

# 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

# 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

# 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)

By default, when generating normals, they will be calculated on a per-vertex basis (i.e. they will be "smooth normals"). If you want flat vertex normals (i.e. a single normal vector per face), when adding vertices, call add_smooth_group(i) where i is a unique number per vertex. add_smooth_group() needs to be called while building the geometry, e.g. before the call to add_vertex().