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.
Checking the stable version of the documentation...
Nutzen des SurfaceTools
Das SurfaceTool bietet eine nützliche Schnittstelle für die Konstruktion von Geometrie. Die Schnittstelle ist ähnlich wie der ImmediateMesh-Klasse. Man setzt jedes Attribut pro Vertex (z.B. normal, uv, Farbe) und wenn man dann einen Vertex hinzufügt, werden die Attribute erfasst.
Das SurfaceTool bietet auch einige nützliche Hilfsfunktionen wie index() und generate_normals().
Attribute werden hinzugefügt, bevor jeder Vertex hinzugefügt wird:
var st = SurfaceTool.new()
st.begin(Mesh.PRIMITIVE_TRIANGLES)
st.set_normal() # Overwritten by normal below.
st.set_normal() # Added to next vertex.
st.set_color() # Added to next vertex.
st.add_vertex() # Captures normal and color above.
st.set_normal() # Normal never added to a vertex.
st.SetNormal(); // Overwritten by normal below.
st.SetNormal(); // Added to next vertex.
st.SetColor(); // Added to next vertex.
st.AddVertex(); // Captures normal and color above.
st.SetNormal(); // Normal never added to a vertex.
When finished generating your geometry with the SurfaceTool,
call commit() to finish generating the mesh. If an ArrayMesh is passed
to commit(), then it appends a new surface to the end of the ArrayMesh. While if nothing is passed
in, commit() returns an ArrayMesh.
# Add surface to existing ArrayMesh.
st.commit(mesh)
# -- Or Alternatively --
# Create new ArrayMesh.
var mesh = st.commit()
st.Commit(mesh);
// Or:
var mesh = st.Commit();
The code below creates a triangle without indices.
var st = SurfaceTool.new()
st.begin(Mesh.PRIMITIVE_TRIANGLES)
# Prepare attributes for add_vertex.
st.set_normal(Vector3(0, 0, 1))
st.set_uv(Vector2(0, 0))
# Call last for each vertex, adds the above attributes.
st.add_vertex(Vector3(-1, -1, 0))
st.set_normal(Vector3(0, 0, 1))
st.set_uv(Vector2(0, 1))
st.add_vertex(Vector3(-1, 1, 0))
st.set_normal(Vector3(0, 0, 1))
st.set_uv(Vector2(1, 1))
st.add_vertex(Vector3(1, 1, 0))
# Commit to a mesh.
var mesh = st.commit()
var st = new SurfaceTool();
st.Begin(Mesh.PrimitiveType.Triangles);
// Prepare attributes for AddVertex.
st.SetNormal(new Vector3(0, 0, 1));
st.SetUV(new Vector2(0, 0));
// Call last for each vertex, adds the above attributes.
st.AddVertex(new Vector3(-1, -1, 0));
st.SetNormal(new Vector3(0, 0, 1));
st.SetUV(new Vector2(0, 1));
st.AddVertex(new Vector3(-1, 1, 0));
st.SetNormal(new Vector3(0, 0, 1));
st.SetUV(new Vector2(1, 1));
st.AddVertex(new Vector3(1, 1, 0));
// Commit to a mesh.
var mesh = st.Commit();
You can optionally add an index array, either by calling add_index() and adding
vertices to the index array manually, or by calling index() once,
which generates the index array automatically and
shrinks the vertex array to remove duplicate vertices.
# Suppose we have a quad defined by 6 vertices as follows
st.add_vertex(Vector3(-1, 1, 0))
st.add_vertex(Vector3(1, 1, 0))
st.add_vertex(Vector3(-1, -1, 0))
st.add_vertex(Vector3(1, 1, 0))
st.add_vertex(Vector3(1, -1, 0))
st.add_vertex(Vector3(-1, -1, 0))
# We can make the quad more efficient by using an index array and only utilizing 4 vertices:
st.add_vertex(Vector3(-1, 1, 0))
st.add_vertex(Vector3(1, 1, 0))
st.add_vertex(Vector3(-1, -1, 0))
st.add_vertex(Vector3(1, -1, 0))
# Creates a quad from four corner vertices.
# add_index() can be called before or after add_vertex()
# since it's not an attribute of a vertex itself.
st.add_index(0)
st.add_index(1)
st.add_index(2)
st.add_index(1)
st.add_index(3)
st.add_index(2)
# Alternatively we can use ``st.index()`` which will create the quad for us and remove the duplicate vertices
st.index()
// Suppose we have a quad defined by 6 vertices as follows.
st.AddVertex(new Vector3(-1, 1, 0));
st.AddVertex(new Vector3(1, 1, 0));
st.AddVertex(new Vector3(-1, -1, 0));
st.AddVertex(new Vector3(1, 1, 0));
st.AddVertex(new Vector3(1, -1, 0));
st.AddVertex(new Vector3(-1, -1, 0));
// We can make the quad more efficient by using an index array and only utilizing 4 vertices:
st.AddVertex(new Vector3(-1, -1, 0));
st.AddVertex(new Vector3(1, 1, 0));
st.AddVertex(new Vector3(-1, -1, 0));
st.AddVertex(new Vector3(1, 1, 0));
// Creates a quad from four corner vertices.
// AddIndex does not need to be called before AddVertex.
st.AddIndex(0);
st.AddIndex(1);
st.AddIndex(2);
st.AddIndex(1);
st.AddIndex(3);
st.AddIndex(2);
// Alternatively we can use `st.Index()` which will create the quad for us and remove the duplicate vertices.
st.Index();
Ähnlich verhält es sich, wenn Sie ein Index-Array haben, aber wollen, dass jeder Vertex eindeutig ist (z.B. weil Sie eindeutige Normalen oder Farben pro Fläche statt pro Vertex verwenden wollen), können Sie deindex() aufrufen.
st.deindex()
st.Deindex();
Wenn Sie keine eigenen Normalen hinzufügen, können Sie sie mit generate_normals() hinzufügen, was nach der Erzeugung der Geometrie und vor der Übergabe des Meshs mit commit() oder commit_to_arrays() aufgerufen werden sollte. Der Aufruf von generate_normals(true) wird die resultierenden Normalen umkehren. Nebenbei bemerkt, generate_normals() funktioniert nur, wenn der primitive Typ auf Mesh.PRIMITIVE_TRIANGLES gesetzt ist.
Möglicherweise werden Sie feststellen, dass das Normal Mapping oder andere Material-Propertys auf dem generierten Mesh nicht korrekt aussehen. Das liegt daran, dass die Normalenabbildung erfordert, dass das Mesh Tangenten aufweist, die von den Normalen getrennt sind. Sie können entweder manuell eigene Tangenten hinzufügen oder sie automatisch mit generate_tangents() erzeugen. Diese Methode setzt voraus, dass jeder Vertex bereits UVs und Normalen gesetzt hat.
st.generate_normals()
st.generate_tangents()
st.commit(mesh)
st.GenerateNormals();
st.GenerateTangents();
By default, when generating normals, they will be calculated on a per-vertex basis (i.e. they will
be "smooth normals"). If you want flat vertex normals (i.e. a single normal vector per face), when
adding vertices, call add_smooth_group(i) where i is a unique number per vertex.
add_smooth_group() needs to be called while building the geometry, e.g. before the call to
add_vertex().