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.

Utilisation du MeshDataTool

Le MeshDataTool n'est pas utilisé pour générer de la géométrie. Mais il est utile pour modifier dynamiquement la géométrie, par exemple si vous voulez écrire un script pour tesseler, simplifier ou déformer des maillages.

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.

Note

MeshDataTool ne peut être utilisé que sur les maillages qui utilisent le PrimitiveType Mesh.PRIMITIVE_TRIANGLES.

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.

Dans les exemples ci-dessous, assumons qu'une ArrayMesh appelée mesh a déjà été créée. Voir ArrayMesh tutorial pour un exemple de génération de maillage.

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

create_from_surface() utilise les tableaux de sommets du ArrayMesh pour calculer deux tableaux supplémentaires, un pour les arêtes et un pour les faces, pour un total de 3 tableaux.

Une arête est une connexion entre deux sommets. Chaque arête de l'array d'arêtes contient une référence aux deux sommets qui la composent et jusqu'à deux faces dans lesquelles elle est contenue.

Une face est un triangle composé de trois sommets et de trois arêtes correspondantes. Chaque face du tableau de faces contient une référence aux trois sommets et aux trois arêtes qui la composent.

Le tableaux des sommets contient les arêtes, les faces, les normales, les couleurs, les tangentes, les uv, les uv2, les os et les informations de poids liées à chaque vertex.

Pour accéder aux informations de ces tableaux, vous utilisez une fonction de la forme 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.

Ce que vous choisissez de faire avec ces fonctions dépend de vous. Un cas d'utilisation courant consiste à parcourir tous les sommets et à les transformer d'une manière ou d'une autre :

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)

Ces modifications ne sont pas effectuées sur l'ArrayMesh. Si vous mettez à jour dynamiquement un ArrayMesh existant, supprimez d'abord la surface existante avant d'en ajouter une nouvelle en utilisant commit_to_surface() :

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

Ci-dessous est un exemple complet qui transforme un maillage sphérique appelé mesh en un blob aléatoirement déformé avec les normales et les couleurs du sommet mises à jour. Voir le tutoriel ArrayMesh pour apprendre à générer un maillage de base.

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)