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.
The first parameter is the PrimitiveType
, an OpenGL concept that instructs the GPU
how to arrange the primitive based on the vertices given, i.e. whether they represent triangles,
lines, points, etc. See Mesh.PrimitiveType for the options available.
The second parameter, arrays
, is the actual Array that stores the mesh information. The array is a
normal Godot array that is constructed with empty brackets []
. It stores a Pool**Array
(e.g. PoolVector3Array, PoolIntArray, etc.) for each type of information that will be used to build the surface.
Les éléments possibles de arrays
sont listés ci-dessous, avec la position qu'ils doivent avoir dans arrays
. Voir aussi Mesh.ArrayType.
Index |
Mesh.ArrayType Enum |
Array type |
---|---|---|
0 |
|
|
1 |
|
|
2 |
|
PoolRealArray of groups of 4 floats. First 3 floats determine the tangent, and the last the binormal direction as -1 or 1. |
3 |
|
|
4 |
|
|
5 |
|
|
6 |
|
PoolRealArray of groups of 4 floats or PoolIntArray of groups of 4 ints. Each group lists indexes of 4 bones that affects a given vertex. |
7 |
|
PoolRealArray of groups of 4 floats. Each float lists the amount of weight an determined bone on |
8 |
|
The array of vertices (at index 0) is always required. The index array is optional and will only be used if included. We won't use it in this tutorial.
Tous les autres tableaux transportent des informations à propos des sommets. Ils sont aussi optionnels et seront uniquement utilisés s'ils sont inclus. Certains de ces tableaux (ex. ARRAY_COLOR
) utilisent une entrée par sommet afin de fournir des informations supplémentaires sur les sommets. Ils doivent avoir la même taille que le tableau des sommets. Les autres tableaux (ex. ARRAY_TANGENT
) utilisent quatre entrées pour décrire un seul sommet. Ceux-ci doivent être exactement quatre fois plus grand que le tableau de sommets.
For normal usage, the last two parameters in add_surface_from_arrays() are typically left empty.
ArrayMesh¶
In the editor, create a MeshInstance 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 MeshInstance.
Sous _ready()
, créez un nouvel Array.
var surface_array = []
This will be the array that we keep our surface information in - it will hold
all the arrays of data that the surface needs. Godot will expect it to be of
size Mesh.ARRAY_MAX
, so resize it accordingly.
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 = 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.
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
mesh.add_surface_from_arrays(Mesh.PRIMITIVE_TRIANGLES, surface_array) # 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.
Put together, the full code looks like:
extends MeshInstance
func _ready():
var surface_array= []
surface_array.resize(Mesh.ARRAY_MAX)
# PoolVector**Arrays 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.
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.
mesh.add_surface_from_arrays(Mesh.PRIMITIVE_TRIANGLES, surface_array) # No blendshapes or compression used.
The code that goes in the middle can be whatever you want. Below we will present some example code for generating a sphere.
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():
# Insert setting up the PoolVector**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):
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
# Insert committing to the ArrayMesh here.
Enregistrer¶
Finally, we can use the ResourceSaver class to save the ArrayMesh. This is useful when you want to generate a mesh and then use it later without having to re-generate it.
# Saves mesh to a .tres file with compression enabled.
ResourceSaver.save("res://sphere.tres", mesh, ResourceSaver.FLAG_COMPRESS)