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 ArrayMesh

Ce tutoriel présente les bases de l'utilisation d'un ArrayMesh.

To do so, we will use the function add_surface_from_arrays(), which takes up to five parameters. The first two are required, while the last three are optional.

Le premier est le PrimitiveType, c'est un concept OpenGL qui indique au GPU comment arranger la primitive en fonction des sommets donnés, qu'il s'agisse de triangles, de lignes, de points, etc. Voir Mesh.PrimitiveType pour les options disponibles.

Le deuxième paramètre, arrays, est le véritable Array qui stocke les informations de maillage. Le tableau est un tableau Godot normal qui est construit avec des crochets vides []. Il stocke un Packed**Array (par exemple, PackedVector3Array, PackedInt32Array, etc.) pour chaque type d'informations qui seront utilisées pour construire la surface.

Common elements of arrays are listed below, together with the position they must have within arrays. See Mesh.ArrayType for a full list.

Index

Mesh.ArrayType Enum

Type de tableau (array)

0

ARRAY_VERTEX

PackedVector3Array ou PackedVector2Array

1

ARRAY_NORMAL

PackedVector3Array

2

ARRAY_TANGENT

PackedFloat32Array ou PackedFloat64Array en groupe de 4 flottants. Les trois premiers flottants déterminent la tangente, et le dernier flottant la direction binormale en -1 ou 1.

3

ARRAY_COLOR

PackedColorArray

4

ARRAY_TEX_UV

PackedVector2Array ou PackedVector3Array

5

ARRAY_TEX_UV2

PackedVector2Array ou PackedVector3Array

10

ARRAY_BONES

PackedFloat32Array en groupes de 4 flottants ou PackedInt32Array en groupes de 4 entiers. Chaque groupe énumère les index des 4 os qui affectent un sommet donné.

11

ARRAY_WEIGHTS

PackedFloat32Array ou PackedFloat64Array en groupes de 4 flottants. Chaque flottant liste la quantité de poids que l'os correspondant dans ARRAY_BONES a sur un sommet donné.

12

ARRAY_INDEX

PackedInt32Array

In most cases when creating a mesh, we define it by its vertex positions. So usually, the array of vertices (at index 0) is required, while the index array (at index 12) is optional and will only be used if included. It is also possible to create a mesh with only the index array and no vertex array, but that's beyond the scope of this tutorial.

All the other arrays carry information about the vertices. They are optional and will only be used if included. Some of these arrays (e.g. ARRAY_COLOR) use one entry per vertex to provide extra information about vertices. They must have the same size as the vertex array. Other arrays (e.g. ARRAY_TANGENT) use four entries to describe a single vertex. These must be exactly four times larger than the vertex array.

For normal usage, the last three parameters in add_surface_from_arrays() are typically left empty.

Setting up the ArrayMesh

In the editor, create a MeshInstance3D and add an ArrayMesh to it in the Inspector. Normally, adding an ArrayMesh in the editor is not useful, but in this case it allows us to access the ArrayMesh from code without creating one.

Ensuite, ajoutez un script au MeshInstance3D.

Sous _ready(), créez un nouvel Array.

var surface_array = []

Ce sera le tableau dans lequel nous conserverons nos informations de surface, il contiendra tous les tableaux de données dont la surface a besoin. Godot s'attendra à ce qu'il soit de taille Mesh.ARRAY_MAX, alors redimensionnez-le en conséquence.

var surface_array = []
surface_array.resize(Mesh.ARRAY_MAX)

Créez ensuite les arrays pour chaque type de données que vous utiliserez.

var verts = PackedVector3Array()
var uvs = PackedVector2Array()
var normals = PackedVector3Array()
var indices = PackedInt32Array()

Une fois que vous avez rempli vos arrays de données avec votre géométrie, vous pouvez créer un maillage en ajoutant chaque array à surface_array, puis en validant le maillage.

surface_array[Mesh.ARRAY_VERTEX] = verts
surface_array[Mesh.ARRAY_TEX_UV] = uvs
surface_array[Mesh.ARRAY_NORMAL] = normals
surface_array[Mesh.ARRAY_INDEX] = indices

# No blendshapes, lods, or compression used.
mesh.add_surface_from_arrays(Mesh.PRIMITIVE_TRIANGLES, surface_array)

Note

Dans cet exemple, nous avons utilisé Mesh.PRIMITIVE_TRIANGLES, mais vous pouvez utiliser n'importe quel type primitif disponible à partir de mesh.

Mis ensemble, le code complet ressemble à ceci :

extends MeshInstance3D

func _ready():
    var surface_array = []
    surface_array.resize(Mesh.ARRAY_MAX)

    # PackedVector**Arrays for mesh construction.
    var verts = PackedVector3Array()
    var uvs = PackedVector2Array()
    var normals = PackedVector3Array()
    var indices = PackedInt32Array()

    #######################################
    ## Insert code here to generate mesh ##
    #######################################

    # Assign arrays to surface array.
    surface_array[Mesh.ARRAY_VERTEX] = verts
    surface_array[Mesh.ARRAY_TEX_UV] = uvs
    surface_array[Mesh.ARRAY_NORMAL] = normals
    surface_array[Mesh.ARRAY_INDEX] = indices

    # Create mesh surface from mesh array.
    # No blendshapes, lods, or compression used.
    mesh.add_surface_from_arrays(Mesh.PRIMITIVE_TRIANGLES, surface_array)

Le code qui va au milieu peut être ce que vous voulez. Ci-dessous, nous présenterons un exemple de code pour générer une sphère.

Génération de la géométrie

Voici un exemple de code pour générer une sphère. Bien que le code soit présenté en GDScript, il n'y a rien de spécifique à Godot dans l'approche de sa génération. Cette implémentation n'a rien de particulier à voir avec ArrayMeshes et n'est qu'une approche générique pour générer une sphère. Si vous avez du mal à comprendre ou si vous souhaitez en savoir plus sur la géométrie procédurale en général, vous pouvez utiliser n'importe quel tutoriel que vous trouverez en ligne.

extends MeshInstance3D

var rings = 50
var radial_segments = 50
var radius = 1

func _ready():

    # Insert setting up the PackedVector**Arrays here.

    # Vertex indices.
    var thisrow = 0
    var prevrow = 0
    var point = 0

    # Loop over rings.
    for i in range(rings + 1):
        var v = float(i) / rings
        var w = sin(PI * v)
        var y = cos(PI * v)

        # Loop over segments in ring.
        for j in range(radial_segments + 1):
            var u = float(j) / radial_segments
            var x = sin(u * PI * 2.0)
            var z = cos(u * PI * 2.0)
            var vert = Vector3(x * radius * w, y * radius, z * radius * w)
            verts.append(vert)
            normals.append(vert.normalized())
            uvs.append(Vector2(u, v))
            point += 1

            # Create triangles in ring using indices.
            if i > 0 and j > 0:
                indices.append(prevrow + j - 1)
                indices.append(prevrow + j)
                indices.append(thisrow + j - 1)

                indices.append(prevrow + j)
                indices.append(thisrow + j)
                indices.append(thisrow + j - 1)

        prevrow = thisrow
        thisrow = point

  # Insert committing to the ArrayMesh here.

Enregistrer

Enfin, nous pouvons sauvegarder l'ArrayMesh en utilisant la classe ResourceSaver. Ceci est utile lorsque vous souhaitez générer un maillage, puis l'utiliser plus tard sans avoir à le générer de nouveau.

# Saves mesh to a .tres file with compression enabled.
ResourceSaver.save(mesh, "res://sphere.tres", ResourceSaver.FLAG_COMPRESS)