Skip to content

Commit 8e327b1

Browse files
authored
Merge pull request godotengine#8272 from clayjohn/ImmediateMesh
Update references to the ImmediateMesh in the Procedural Geometry tutorial
2 parents 548c600 + f23d6b0 commit 8e327b1

File tree

2 files changed

+86
-47
lines changed

2 files changed

+86
-47
lines changed

tutorials/3d/procedural_geometry/immediatemesh.rst

Lines changed: 68 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -3,25 +3,33 @@
33
Using ImmediateMesh
44
===================
55

6-
Unlike the SurfaceTool or ArrayMesh, :ref:`ImmediateMesh <class_ImmediateMesh>` is an actual
7-
node. Being a node makes it quick to add to a scene and get visual output. It uses an OpenGL 1.x-style
8-
API like SurfaceTool, but it's actually designed to create meshes on the fly.
6+
The :ref:`ImmediateMesh <class_ImmediateMesh>` is a convenient tool to create
7+
dynamic geometry using an OpenGL 1.x-style API. Which makes it both approachable
8+
to use and efficient for meshes which need to be updated every frame.
99

10-
Generating complex geometry (several thousand vertices) with this node is inefficient, even if it's
10+
Generating complex geometry (several thousand vertices) with this tool is inefficient, even if it's
1111
done only once. Instead, it is designed to generate simple geometry that changes every frame.
1212

13-
Before starting, you should clear the geometry by calling ``clear_surfaces()``. This ensures that
14-
you are not building upon the geometry from the previous frame. If you want to keep geometry between frames, do
15-
not call ``clear_surfaces()``.
13+
First, you need to create a :ref:`MeshInstance3D <class_meshinstance3d>` and add
14+
an :ref:`ImmediateMesh <class_ImmediateMesh>` to it in the Inspector.
1615

17-
To begin generating geometry you must call ``surface_begin()``. ``surface_begin()`` takes a ``PrimitiveType`` as an argument.
18-
``PrimitiveType`` is an OpenGL concept that instructs the GPU how to arrange the primitive based on the
19-
vertices given whether it is triangles, lines, points, etc. A complete list can be found under
16+
Next, add a script to the MeshInstance3D. The code for the ImmediateMesh should
17+
go in the ``_process()`` function if you want it to update each frame, or in the
18+
``_ready()`` function if you want to create the mesh once and not update it. If
19+
you only generate a surface once, the ImmediateMesh is just as efficient as any
20+
other kind of mesh as the generated mesh is cached and reused.
21+
22+
To begin generating geometry you must call ``surface_begin()``.
23+
``surface_begin()`` takes a ``PrimitiveType`` as an argument. ``PrimitiveType``
24+
instructs the GPU how to arrange the primitive based on the vertices given
25+
whether it is triangles, lines, points, etc. A complete list can be found under
2026
the :ref:`Mesh <class_mesh>` class reference page.
2127

22-
Once you have called ``surface_begin()`` you are ready to start adding vertices. You add vertices one at a time.
23-
First you add vertex specific attributes such as normals or UVs using ``surface_set_****()`` (e.g. ``surface_set_normal()``).
24-
Then you call ``surface_add_vertex()`` to add a vertex with those attributes. For example:
28+
Once you have called ``surface_begin()`` you are ready to start adding vertices.
29+
You add vertices one at a time. First you add vertex specific attributes such as
30+
normals or UVs using ``surface_set_****()`` (e.g. ``surface_set_normal()``).
31+
Then you call ``surface_add_vertex()`` to add a vertex with those attributes.
32+
For example:
2533

2634
.. tabs::
2735
.. code-tab:: gdscript GDScript
@@ -31,37 +39,63 @@ Then you call ``surface_add_vertex()`` to add a vertex with those attributes. Fo
3139
surface_set_uv(Vector2(1, 1))
3240
surface_add_vertex(Vector3(0, 0, 1))
3341

34-
Only attributes added before the call to ``surface_add_vertex()`` will be included in that vertex.
42+
Only attributes added before the call to ``surface_add_vertex()`` will be
43+
included in that vertex. If you add an attribute twice before calling
44+
``surface_add_vertex()``, only the second call will be used.
3545

36-
Finally, once you have added all your vertices call ``surface_end()`` to signal that you have finished generating the mesh.
46+
Finally, once you have added all your vertices call ``surface_end()`` to signal
47+
that you have finished generating the surface. You can call ``surface_begin()``
48+
and ``surface_end()`` multiple times to generate multiple surfaces for the mesh.
3749

38-
The example code below draws a single triangle.
50+
The example code below draws a single triangle in the ``_ready()`` function.
3951

4052
.. tabs::
4153
.. code-tab:: gdscript GDScript
4254

43-
extends ImmediateMesh
44-
45-
func _process(_delta):
46-
# Clean up before drawing.
47-
clear_surfaces()
55+
extends MeshInstance3D
4856

57+
func _ready():
4958
# Begin draw.
50-
surface_begin(Mesh.PRIMITIVE_TRIANGLES)
51-
52-
# Prepare attributes for surface_add_vertex.
53-
surface_set_normal(Vector3(0, 0, 1))
54-
surface_set_uv(Vector2(0, 0))
59+
mesh.surface_begin(Mesh.PRIMITIVE_TRIANGLES)
60+
61+
# Prepare attributes for add_vertex.
62+
mesh.surface_set_normal(Vector3(0, 0, 1))
63+
mesh.surface_set_uv(Vector2(0, 0))
5564
# Call last for each vertex, adds the above attributes.
56-
surface_add_vertex(Vector3(-1, -1, 0))
65+
mesh.surface_add_vertex(Vector3(-1, -1, 0))
5766

58-
surface_set_normal(Vector3(0, 0, 1))
59-
surface_set_uv(Vector2(0, 1))
60-
surface_add_vertex(Vector3(-1, 1, 0))
67+
mesh.surface_set_normal(Vector3(0, 0, 1))
68+
mesh.surface_set_uv(Vector2(0, 1))
69+
mesh.surface_add_vertex(Vector3(-1, 1, 0))
6170

62-
surface_set_normal(Vector3(0, 0, 1))
63-
surface_set_uv(Vector2(1, 1))
64-
surface_add_vertex(Vector3(1, 1, 0))
71+
mesh.surface_set_normal(Vector3(0, 0, 1))
72+
mesh.surface_set_uv(Vector2(1, 1))
73+
mesh.surface_add_vertex(Vector3(1, 1, 0))
6574

6675
# End drawing.
67-
surface_end()
76+
mesh.surface_end()
77+
78+
The ImmediateMesh can also be used across frames. Each time you call
79+
``surface_begin()`` and ``surface_end()``, you are adding a new surface to the
80+
ImmediateMesh. If you want to recreate the mesh from scratch each frame, call
81+
``surface_clear()`` before calling ``surface_begin()``.
82+
83+
.. tabs::
84+
.. code-tab:: gdscript GDScript
85+
86+
extends MeshInstance3D
87+
88+
func _process(delta):
89+
90+
# Clean up before drawing.
91+
mesh.clear_surfaces()
92+
93+
# Begin draw.
94+
mesh.surface_begin(Mesh.PRIMITIVE_TRIANGLES)
95+
96+
# Draw mesh.
97+
98+
# End drawing.
99+
mesh.surface_end()
100+
101+
The above code will dynamically create and draw a single surface each frame.

tutorials/3d/procedural_geometry/index.rst

Lines changed: 18 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -30,9 +30,12 @@ by an array of positions called "vertices". In Godot, geometry is represented by
3030
What is a Mesh?
3131
---------------
3232

33-
Many things in Godot have mesh in their name: the :ref:`Mesh <class_Mesh>`, the :ref:`ArrayMesh <class_ArrayMesh>`,
34-
the :ref:`MeshInstance3D <class_MeshInstance3D>`, the :ref:`MultiMesh <class_MultiMesh>`, and
35-
the :ref:`MultiMeshInstance3D <class_MultiMeshInstance3D>`. While they are all related, they have slightly different uses.
33+
Many things in Godot have mesh in their name: the :ref:`Mesh <class_Mesh>`, the
34+
:ref:`ArrayMesh <class_ArrayMesh>`, the :ref:`ImmediateMesh
35+
<class_ImmediateMesh>`, the :ref:`MeshInstance3D <class_MeshInstance3D>`, the
36+
:ref:`MultiMesh <class_MultiMesh>`, and the :ref:`MultiMeshInstance3D
37+
<class_MultiMeshInstance3D>`. While they are all related, they have slightly
38+
different uses.
3639

3740
Meshes and ArrayMeshes are resources that are drawn using a MeshInstance3D node. Resources like
3841
Meshes and ArrayMeshes cannot be added to the scene directly. A MeshInstance3D represents one
@@ -109,14 +112,16 @@ For more information about the SurfaceTool, please see the :ref:`SurfaceTool tut
109112
ImmediateMesh
110113
^^^^^^^^^^^^^
111114

112-
ImmediateMesh is a node that uses an immediate mode style interface (like SurfaceTool) to draw objects. The
113-
difference between ImmediateMesh and the SurfaceTool is that ImmediateMesh is a node itself that can be
114-
added to the scene tree and is drawn directly from the code, while The SurfaceTool generates a Mesh that needs to be added to
115-
a MeshInstance3D to be seen.
115+
ImmediateMesh is a mesh that uses an immediate mode style interface (like
116+
SurfaceTool) to draw objects. The difference between ImmediateMesh and the
117+
SurfaceTool is that ImmediateMesh is drawn directly with code dynamically, while
118+
the SurfaceTool is used to generated a Mesh that you can do whatever you want
119+
with.
116120

117-
ImmediateMesh is useful for prototyping because of its straightforward API, but it is slow because the geometry
118-
is rebuilt every frame. It is most useful for adding simple geometry for visual debugging (e.g. by drawing lines to
119-
visualize physics raycasts etc.).
121+
ImmediateMesh is useful for prototyping because of its straightforward API, but
122+
it is slow because the geometry is rebuilt each time you make a change. It is
123+
most useful for adding simple geometry for visual debugging (e.g. by drawing
124+
lines to visualize physics raycasts etc.).
120125

121126
For more information about ImmediateMesh, please see the :ref:`ImmediateMesh tutorial <doc_immediatemesh>`.
122127

@@ -130,9 +135,9 @@ Both SurfaceTool and ArrayMesh are excellent for generating static geometry (mes
130135
Using an ArrayMesh is slightly faster than using a SurfaceTool, but the API is a little more challenging.
131136
Additionally, SurfaceTool has a few quality of life methods such as ``generate_normals()`` and ``index()``.
132137

133-
ImmediateMesh regenerates the mesh every frame, so it is much slower than ArrayMesh or SurfaceTool. However, if you
134-
need the geometry to change every frame anyway, it provides a much easier interface that may even be a little faster than generating
135-
an ArrayMesh every frame.
138+
ImmediateMesh is more limited than both ArrayMesh and SurfaceTool. However, if
139+
you need the geometry to change every frame anyway, it provides a much easier
140+
interface that can be slightly faster than generating an ArrayMesh every frame.
136141

137142
The MeshDataTool is not fast, but it gives you access to all kinds of properties of the mesh that you don't get with the others
138143
(edges, faces, etc.). It is incredibly useful when you need that sort of data to transform the mesh, but it is not a good idea

0 commit comments

Comments
 (0)