Attention: Here be dragons

This is the latest (unstable) version of this documentation, which may document features not available in or compatible with released stable versions of Godot.

使用 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() 之前。