Utilisation du ArrayMesh

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

Pour ce faire, nous utiliserons la fonction add_surface_from_arrays(), qui prend jusqu’à quatre paramètres. Les deux premiers sont obligatoires, tandis que les deux autres sont facultatifs.

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. Une liste complète peut être trouvée sur la page de référence de la classe Mesh.

Le second est le Array réel qui stocke les informations sur le maillage. Le array est un array de Godot normal qui est construit avec des crochets vides []. Il stocke un Pool**Array (par exemple PoolVector3Array, PoolIntArray, etc.) pour chaque type d’information.

  • ARRAY_VERTEX = 0 | PoolVector3Array ou PoolVector2Array
  • ARRAY_NORMAL = 1 | PoolVector3Array
  • ARRAY_TANGENT = 2 | PoolRealArray de groupes de 4 flottants. Les 3 premiers flottants déterminent la tangente, et le dernier la direction binaire comme -1 ou 1.
  • ARRAY_COLOR = 3 | PoolColorArray
  • ARRAY_TEX_UV = 4 | PoolVector2Array ou PoolVector3Array
  • ARRAY_TEX_UV2 = 5 | PoolVector2Array ou PoolVector3Array
  • ARRAY_BONES = 6 | PoolRealArray de groupes de 4 flottants ou PoolIntArray de groupes de 4 ints
  • ARRAY_WEIGHTS = 7 | PoolRealArray de groupes de 4 flottants
  • ARRAY_INDEX = 8 | PoolIntArray

L’Array des sommets est toujours requis. Tous les autres sont facultatifs et ne seront utilisés que s’ils sont inclus.

Chaque array doit avoir le même nombre d’éléments que l’array des sommets, à l’exception de l’array des index. Pour les arrays comme les tangentes, un élément est un groupe de 4 flottants. La taille de l’array sera donc quatre fois plus grande que celle de l’array des sommets, mais ils auront le même nombre d’éléments

L’array des index est unique.

Le troisième paramètre est un ensemble de blendshapes à utiliser pour le Mesh. Bien que ce tutoriel ne couvre pas l’utilisation des blendshapes, il est possible de les spécifier lors de la création d’une surface à partir d’arrays.

Le dernier paramètre est les drapeaux de compression qui spécifient les arrays à stocker avec deux fois moins de bits. Les valeurs peuvent être trouvées dans la classref pour VisualServer sous ArrayFormat.

Pour une utilisation normale, il est préférable de laisser les deux derniers paramètres vides.

ArrayMesh

Ajoutez un ArrayMesh à une MeshInstance. Normalement, l’ajout d’un ArrayMesh dans l’éditeur n’est pas utile, mais dans ce cas il permet d’accéder au ArrayMesh à partir du code sans en créer un.

Ensuite, ajoutez un script au MeshInstance.

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

var arr = []

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

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

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

var verts = PoolVector3Array()
var uvs = PoolVector2Array()
var normals = PoolVector3Array()
var indices = PoolIntArray()

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.

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

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

Note

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

Le code complet ressemble à ceci :

extends MeshInstance

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

    # PoolVectorXXArrays for mesh construction.
    var verts = PoolVector3Array()
    var uvs = PoolVector2Array()
    var normals = PoolVector3Array()
    var indices = PoolIntArray()

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

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

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

Le code qui va au milieu peut être ce que vous voulez. Ci-dessous, nous présenterons un exemple de code qui pourrait aller au milieu.

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 MeshInstance

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

func _ready():

    # Set up the PoolVectorXArrays.

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

        if i > 0:
            indices.append(prevrow + radial_segments - 1)
            indices.append(prevrow)
            indices.append(thisrow + radial_segments - 1)

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

        prevrow = thisrow
        thisrow = point

  # Commit to the ArrayMesh.

Combiné avec le code ci-dessus, ce code va générer une sphère.

Quand il s’agit de générer une géométrie avec ArrayMesh, vous devez comprendre ce qui se passe dans chaque array, puis vous pouvez suivre des tutoriels pour n’importe quel langage/moteur et le convertir dans Godot.

Enregistrer

Enfin, Godot fournit une méthode unique pour enregistrer ArrayMeshes en utilisant la classe ResourceSaver. Ceci est utile lorsque vous souhaitez générer un maillage, puis l’utiliser plus tard sans avoir à générer de nouveau.

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