Usando o ArrayMesh¶
This tutorial will present the basics of using an ArrayMesh.
To do so, we will use the function add_surface_from_arrays(), which takes up to four parameters. The first two are required, while the second two are optional.
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.
The possible elements of arrays
are listed below, together with the position they must have within arrays
.
See also Mesh.ArrayType.
Índice |
Mesh.ArrayType Enum |
Tipo de matriz |
---|---|---|
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.
All the other arrays carry information about the vertices. They are also 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 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.
Em seguida, adicione um script à MeshInstance.
Em ''_ready()'', crie uma nova Array.
var surface_array = []
Esta será a matriz na qual manteremos nossas informações de superfície - ela conterá todas as matrizes de dados que a superfície necessita. Godot espera que ela seja do tamanho Mesh.ARRAY_MAX
, portanto, redimensione-a de acordo.
var surface_array = []
surface_array.resize(Mesh.ARRAY_MAX)
Em seguida, crie as matrizes para cada tipo de dado que você usará.
var verts = PoolVector3Array()
var uvs = PoolVector2Array()
var normals = PoolVector3Array()
var indices = PoolIntArray()
Uma vez que você tenha preenchido suas matrizes de dados com sua geometria, você pode criar uma malha adicionando cada matriz a surface_array
e, em seguida, comitando para a malha.
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.
Nota
Neste exemplo, utilizamos Mesh.PRIMITIVE_TRIANGLES
, mas você pode utilizar qualquer tipo primitivo disponível na malha.
Juntos, o código completo se parece com:
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.
O código que vai no meio pode ser o que você quiser. A seguir apresentaremos um exemplo de código para gerar uma esfera.
Gerando geometria¶
Aqui está uma amostra de código para gerar uma esfera. Embora o código seja apresentado no GDScript, não há nada de específico do Godot sobre a abordagem para gerá-lo. Esta implementação não tem nada em particular a ver com ArrayMeshes e é apenas uma abordagem genérica para a geração de uma esfera. Se você estiver tendo problemas para compreendê-la ou quiser aprender mais sobre a geometria de procedimentos em geral, você pode usar qualquer tutorial que encontrar on-line.
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.
Salvando¶
Finalmente, podemos usar a classe :ref:'ResourceSaver<class_resourcesaver>' para salvar a ArrayMesh. Isso é útil quando você deseja gerar uma malha e, em seguida, usá-la mais tarde sem ter que gerá-la novamente.
# Saves mesh to a .tres file with compression enabled.
ResourceSaver.save("res://sphere.tres", mesh, ResourceSaver.FLAG_COMPRESS)