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.

使用 MeshDataTool

MeshDataTool 不是用來生成幾何體的, 但它對動態改變幾何體很有説明, 例如, 如果你想寫一個腳本來分割, 簡化或變形網格.

The MeshDataTool is not as fast as altering arrays directly using ArrayMesh. However, it provides more information and tools to work with meshes than the ArrayMesh does. When the MeshDataTool is used, it calculates mesh data that is not available in ArrayMeshes such as faces and edges, which are necessary for certain mesh algorithms. If you do not need this extra information then it may be better to use an ArrayMesh.

備註

MeshDataTool 只能用於使用 Mesh.PRIMITIVE_TRIANGLES PrimitiveType 的網格。

We initialize the MeshDataTool from an ArrayMesh by calling create_from_surface(). If there is already data initialized in the MeshDataTool, calling create_from_surface() will clear it for you. Alternatively, you can call clear() yourself before re-using the MeshDataTool.

下面的例子中,假定已經建立了一個名叫 mesh 的 ArrayMesh。網格生成的範例見 ArrayMesh 教學

var mdt = MeshDataTool.new()
mdt.create_from_surface(mesh, 0)

create_from_surface() 使用 ArrayMesh 中的頂點陣列來計算另外兩個陣列,一個是邊、一個是面,總計三個陣列。

邊緣是任意兩個頂點之間的連接. 邊緣陣列中的每一條邊緣都包含了對它所組成的兩個頂點的引用, 以及它所包含的最多的兩個面.

面是由三個頂點和三條對應的邊組成的三角形. 面陣列中的每個面都包含了它所組成的三個三角形和三條邊的參考.

頂點陣列包含與每個頂點相連的邊、面、法線、顏色、切線、uv、uv2、骨骼和權重信息。

為了從這些陣列中獲取資訊, 你可以使用 get_ **** () 的函式:

mdt.get_vertex_count() # Returns the number of vertices in the vertex array.
mdt.get_vertex_faces(0) # Returns an array of faces that contain vertex[0].
mdt.get_face_normal(1) # Calculates and returns the face normal of the second face.
mdt.get_edge_vertex(10, 1) # Returns the second vertex comprising the edge at index 10.

你選擇用這些函式做什麼取決於你。一個常見的用例是對所有頂點進行反覆運算,並以某種方式對它們進行轉換:

for i in range(mdt.get_vertex_count()):
    var vert = mdt.get_vertex(i)
    vert *= 2.0 # Scales the vertex by doubling its size.
    mdt.set_vertex(i, vert)

這些修改不是在 ArrayMesh 上直接進行的。如果你要動態更新現有的 ArrayMesh,請在新增新表面前使用 commit_to_surface() 來刪除已有表面:

mesh.clear_surfaces() # Deletes all of the mesh's surfaces.
mdt.commit_to_surface(mesh)

下面是一個完整的範例,將一個叫做 mesh 的球體網格變成隨機變形的塊狀,法線和頂點顏色也進行了更新。如何生成基礎網格見 ArrayMesh 教學

extends MeshInstance3D

var fnl = FastNoiseLite.new()
var mdt = MeshDataTool.new()

func _ready():
    fnl.frequency = 0.7

    mdt.create_from_surface(mesh, 0)

    for i in range(mdt.get_vertex_count()):
        var vertex = mdt.get_vertex(i).normalized()
        # Scale the vertices using noise.
        vertex = vertex * (fnl.get_noise_3dv(vertex) * 0.5 + 0.75)
        mdt.set_vertex(i, vertex)

    # Calculate the vertex normals, face-by-face.
    for i in range(mdt.get_face_count()):
        # Get the index in the vertex array.
        var a = mdt.get_face_vertex(i, 0)
        var b = mdt.get_face_vertex(i, 1)
        var c = mdt.get_face_vertex(i, 2)
        # Get the vertex position using the vertex index.
        var ap = mdt.get_vertex(a)
        var bp = mdt.get_vertex(b)
        var cp = mdt.get_vertex(c)
        # Calculate the normal of the face.
        var n = (bp - cp).cross(ap - bp).normalized()
        # Add this face normal to the current vertex normals.
        # This will not result in perfect normals, but it will be close.
        mdt.set_vertex_normal(a, n + mdt.get_vertex_normal(a))
        mdt.set_vertex_normal(b, n + mdt.get_vertex_normal(b))
        mdt.set_vertex_normal(c, n + mdt.get_vertex_normal(c))

    # Run through the vertices one last time to normalize their normals and
    # set the vertex colors to these new normals.
    for i in range(mdt.get_vertex_count()):
        var v = mdt.get_vertex_normal(i).normalized()
        mdt.set_vertex_normal(i, v)
        mdt.set_vertex_color(i, Color(v.x, v.y, v.z))

    mesh.clear_surfaces()
    mdt.commit_to_surface(mesh)