使用 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

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

預設在產生法線時,會以每個頂點為基礎計算(即「平滑法線」)。若你想要平坦法線(每個面只有一個法線向量),在新增頂點時呼叫 add_smooth_group(i),其中 i 對每個頂點為唯一值。add_smooth_group() 必須在建立幾何的過程中呼叫,例如在呼叫 add_vertex() 之前。