Nutzen des ArrayMesh¶
In dieser Anleitung werden die Grundlagen der Verwendung eines ArrayMesh erläutert.
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 is the PrimitiveType
, this is an OpenGL concept that instructs the GPU
how to arrange the primitive based on the vertices given whether it is triangles,
lines, points, etc. A complete list can be found under the Mesh
class reference page.
The second 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.
ARRAY_VERTEX
= 0 | PoolVector3Array oder PoolVector2ArrayARRAY_NORMAL
= 1 | PoolVector3ArrayARRAY_TANGENT
= 2 | PoolRealArray aus Gruppen von 4 Fließkommazahlen. Die ersten 3 Fließkommazahlen bestimmen die Tangente und die letzte die binormale Richtung als -1 oder 1.ARRAY_COLOR
= 3 | PoolColorArrayARRAY_TEX_UV
= 4 | PoolVector2Array oder PoolVector3ArrayARRAY_TEX_UV2
= 5 | PoolVector2Array oder PoolVector3ArrayARRAY_BONES
= 6 | PoolRealArray aus Gruppen mit 4 Fließkommazahlen oder PoolIntArray aus Gruppen mit 4 GanzzahlenARRAY_WEIGHTS
= 7 | PoolRealArray aus Gruppen von 4 FließkommazahlenARRAY_INDEX
= 8 | PoolIntArray
Das Array von Eckpunkten ist immer erforderlich. Alle anderen sind optional und werden nur verwendet, wenn sie enthalten sind.
Each array needs to have the same number of elements as the vertex array except for the index array. For arrays like tangents, an element is a group of 4 floats. So the array size will be four times the size of the vertex array size, but they will have the same number of elements
Das Index-Array ist eindeutig.
The third parameter is an array of blendshapes for the Mesh to use. While this tutorial does not cover using blendshapes, it is possible to specify them when creating a surface from arrays.
The last parameter is the compress flags which specifies which arrays to store with half as many bits. The values can be found in the classref for VisualServer under ArrayFormat.
Für den normalen Gebrauch ist es am besten die letzten beiden Parameter leer zu lassen.
ArrayMesh¶
Add an ArrayMesh to a MeshInstance. Normally, adding an ArrayMesh in the editor is not useful, but in this case it allows as to access the ArrayMesh from code without creating one.
Fügen Sie als Nächstes der MeshInstance ein Skript hinzu.
Unter _ready()
erzeugen wir ein neues Array.
var arr = []
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 arr = []
arr.resize(Mesh.ARRAY_MAX)
Erstellen Sie als Nächstes die Arrays für jeden Datentyp, den Sie verwenden möchten.
var verts = PoolVector3Array()
var uvs = PoolVector2Array()
var normals = PoolVector3Array()
var indices = PoolIntArray()
Once you have filled your data arrays with your geometry you can create a mesh
by adding each array to surface_array
and then committing to the mesh.
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.
Bemerkung
In this example, we used Mesh.PRIMITIVE_TRIANGLES
, but you can use any primitive type
available from mesh.
Zusammenfassend sieht der vollständige Code so aus:
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.
Der Code in der Mitte kann beliebig sein. Im Folgenden werden wir einen Beispielcode präsentieren, der in die Mitte stehen könnte.
Generierte Geometrie¶
Here is sample code for generating a sphere. Although the code is presented in GDScript, there is nothing Godot specific about the approach to generating it. This implementation has nothing in particular to do with ArrayMeshes and is just a generic approach to generating a sphere. If you are having trouble understanding it or want to learn more about procedural geometry in general, you can use any tutorial that you find online.
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.
Kombiniert mit dem obigen Code erzeugt dieser Code eine Kugel.
When it comes to generating geometry with the ArrayMesh you need to understand what goes in each array and then you can follow tutorials for any language/engine and convert it into Godot.
Speichern¶
Finally, Godot provides a single method to save ArrayMeshes using the ResourceSaver class. This is useful when you want to generate a mesh and then use it later without having to re-generate.
# Saves mesh to a .tres file with compression enabled.
ResourceSaver.save("res://sphere.tres", mesh, 32)