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.

Verwendung des MeshDataTools

Das MeshDataTool wird nicht zur Erzeugung von Geometrie verwendet. Es ist aber hilfreich, um Geometrie dynamisch zu verändern, zum Beispiel wenn Sie ein Skript schreiben wollen, um Meshes zu tesselieren, zu vereinfachen oder zu verformen.

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.

Bemerkung

MeshDataTool kann nur auf Meshes verwendet werden, die den PrimitiveType Mesh.PRIMITIVE_TRIANGLES verwenden.

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.

In den folgenden Beispielen wird davon ausgegangen, dass ein ArrayMesh namens mesh bereits erstellt wurde. Siehe ArrayMesh tutorial für ein Beispiel der Meshgenerierung.

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

create_from_surface() verwendet die Vertex-Arrays aus dem ArrayMesh, um zwei zusätzliche Arrays zu berechnen, eines für Kanten und eines für Flächen, also insgesamt drei Arrays.

Eine Kante ist eine Verbindung zwischen zwei beliebigen Vertices. Jede Kante im Kanten-Array enthält einen Verweis auf die beiden Vertices, aus denen sie besteht, und bis zu zwei Flächen, in denen sie enthalten ist.

Eine Fläche ist ein Dreieck, das aus drei Vertices und drei entsprechenden Kanten besteht. Jede Fläche im Flächenarray enthält einen Verweis auf die drei Vertices und drei Kanten, aus denen sie besteht.

Das Vertex-Array enthält Kanten-, Flächen-, Normal-, Farb-, Tangenten-, Uv-, Uv2-, Knochen- und Gewichtsinformationen, die mit jedem Vertex verbunden sind.

Um auf Informationen aus diesen Arrays zuzugreifen, verwenden Sie eine Funktion der Form 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.

Was Sie mit diesen Funktionen machen wollen, bleibt Ihnen überlassen. Ein gängiger Anwendungsfall ist die Iteration über alle Vertices und deren Umwandlung in irgendeiner Weise:

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)

Diese Änderungen werden nicht In-Place auf dem ArrayMesh durchgeführt. Wenn Sie ein bestehendes ArrayMesh dynamisch aktualisieren, löschen Sie zuerst die bestehende Oberfläche, bevor Sie eine neue mit commit_to_surface() hinzufügen:

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

Unten ist ein komplettes Beispiel, das ein kugelförmiges Mesh namens Mesh in einen zufällig deformierten Blob mit aktualisierten Normalen und Vertex-Farben verwandelt. Siehe ArrayMesh-Tutorial für die Erzeugung des Basismeshs.

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)