|
@@ -3,25 +3,33 @@
|
|
|
Using ImmediateMesh
|
|
|
===================
|
|
|
|
|
|
-Unlike the SurfaceTool or ArrayMesh, :ref:`ImmediateMesh <class_ImmediateMesh>` is an actual
|
|
|
-node. Being a node makes it quick to add to a scene and get visual output. It uses an OpenGL 1.x-style
|
|
|
-API like SurfaceTool, but it's actually designed to create meshes on the fly.
|
|
|
+The :ref:`ImmediateMesh <class_ImmediateMesh>` is a convenient tool to create
|
|
|
+dynamic geometry using an OpenGL 1.x-style API. Which makes it both approachable
|
|
|
+to use and efficient for meshes which need to be updated every frame.
|
|
|
|
|
|
-Generating complex geometry (several thousand vertices) with this node is inefficient, even if it's
|
|
|
+Generating complex geometry (several thousand vertices) with this tool is inefficient, even if it's
|
|
|
done only once. Instead, it is designed to generate simple geometry that changes every frame.
|
|
|
|
|
|
-Before starting, you should clear the geometry by calling ``clear_surfaces()``. This ensures that
|
|
|
-you are not building upon the geometry from the previous frame. If you want to keep geometry between frames, do
|
|
|
-not call ``clear_surfaces()``.
|
|
|
+First, you need to create a :ref:`MeshInstance3D <class_meshinstance3d>` and add
|
|
|
+an :ref:`ImmediateMesh <class_ImmediateMesh>` to it in the Inspector.
|
|
|
|
|
|
-To begin generating geometry you must call ``surface_begin()``. ``surface_begin()`` takes a ``PrimitiveType`` as an argument.
|
|
|
-``PrimitiveType`` 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
|
|
|
+Next, add a script to the MeshInstance3D. The code for the ImmediateMesh should
|
|
|
+go in the ``_process()`` function if you want it to update each frame, or in the
|
|
|
+``_ready()`` function if you want to create the mesh once and not update it. If
|
|
|
+you only generate a surface once, the ImmediateMesh is just as efficient as any
|
|
|
+other kind of mesh as the generated mesh is cached and reused.
|
|
|
+
|
|
|
+To begin generating geometry you must call ``surface_begin()``.
|
|
|
+``surface_begin()`` takes a ``PrimitiveType`` as an argument. ``PrimitiveType``
|
|
|
+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 :ref:`Mesh <class_mesh>` class reference page.
|
|
|
|
|
|
-Once you have called ``surface_begin()`` you are ready to start adding vertices. You add vertices one at a time.
|
|
|
-First you add vertex specific attributes such as normals or UVs using ``surface_set_****()`` (e.g. ``surface_set_normal()``).
|
|
|
-Then you call ``surface_add_vertex()`` to add a vertex with those attributes. For example:
|
|
|
+Once you have called ``surface_begin()`` you are ready to start adding vertices.
|
|
|
+You add vertices one at a time. First you add vertex specific attributes such as
|
|
|
+normals or UVs using ``surface_set_****()`` (e.g. ``surface_set_normal()``).
|
|
|
+Then you call ``surface_add_vertex()`` to add a vertex with those attributes.
|
|
|
+For example:
|
|
|
|
|
|
.. tabs::
|
|
|
.. code-tab:: gdscript GDScript
|
|
@@ -31,37 +39,63 @@ Then you call ``surface_add_vertex()`` to add a vertex with those attributes. Fo
|
|
|
surface_set_uv(Vector2(1, 1))
|
|
|
surface_add_vertex(Vector3(0, 0, 1))
|
|
|
|
|
|
-Only attributes added before the call to ``surface_add_vertex()`` will be included in that vertex.
|
|
|
+Only attributes added before the call to ``surface_add_vertex()`` will be
|
|
|
+included in that vertex. If you add an attribute twice before calling
|
|
|
+``surface_add_vertex()``, only the second call will be used.
|
|
|
|
|
|
-Finally, once you have added all your vertices call ``surface_end()`` to signal that you have finished generating the mesh.
|
|
|
+Finally, once you have added all your vertices call ``surface_end()`` to signal
|
|
|
+that you have finished generating the surface. You can call ``surface_begin()``
|
|
|
+and ``surface_end()`` multiple times to generate multiple surfaces for the mesh.
|
|
|
|
|
|
-The example code below draws a single triangle.
|
|
|
+The example code below draws a single triangle in the ``_ready()`` function.
|
|
|
|
|
|
.. tabs::
|
|
|
.. code-tab:: gdscript GDScript
|
|
|
|
|
|
- extends ImmediateMesh
|
|
|
-
|
|
|
- func _process(_delta):
|
|
|
- # Clean up before drawing.
|
|
|
- clear_surfaces()
|
|
|
+ extends MeshInstance3D
|
|
|
|
|
|
+ func _ready():
|
|
|
# Begin draw.
|
|
|
- surface_begin(Mesh.PRIMITIVE_TRIANGLES)
|
|
|
-
|
|
|
- # Prepare attributes for surface_add_vertex.
|
|
|
- surface_set_normal(Vector3(0, 0, 1))
|
|
|
- surface_set_uv(Vector2(0, 0))
|
|
|
+ mesh.surface_begin(Mesh.PRIMITIVE_TRIANGLES)
|
|
|
+
|
|
|
+ # Prepare attributes for add_vertex.
|
|
|
+ mesh.surface_set_normal(Vector3(0, 0, 1))
|
|
|
+ mesh.surface_set_uv(Vector2(0, 0))
|
|
|
# Call last for each vertex, adds the above attributes.
|
|
|
- surface_add_vertex(Vector3(-1, -1, 0))
|
|
|
+ mesh.surface_add_vertex(Vector3(-1, -1, 0))
|
|
|
|
|
|
- surface_set_normal(Vector3(0, 0, 1))
|
|
|
- surface_set_uv(Vector2(0, 1))
|
|
|
- surface_add_vertex(Vector3(-1, 1, 0))
|
|
|
+ mesh.surface_set_normal(Vector3(0, 0, 1))
|
|
|
+ mesh.surface_set_uv(Vector2(0, 1))
|
|
|
+ mesh.surface_add_vertex(Vector3(-1, 1, 0))
|
|
|
|
|
|
- surface_set_normal(Vector3(0, 0, 1))
|
|
|
- surface_set_uv(Vector2(1, 1))
|
|
|
- surface_add_vertex(Vector3(1, 1, 0))
|
|
|
+ mesh.surface_set_normal(Vector3(0, 0, 1))
|
|
|
+ mesh.surface_set_uv(Vector2(1, 1))
|
|
|
+ mesh.surface_add_vertex(Vector3(1, 1, 0))
|
|
|
|
|
|
# End drawing.
|
|
|
- surface_end()
|
|
|
+ mesh.surface_end()
|
|
|
+
|
|
|
+The ImmediateMesh can also be used across frames. Each time you call
|
|
|
+``surface_begin()`` and ``surface_end()``, you are adding a new surface to the
|
|
|
+ImmediateMesh. If you want to recreate the mesh from scratch each frame, call
|
|
|
+``surface_clear()`` before calling ``surface_begin()``.
|
|
|
+
|
|
|
+.. tabs::
|
|
|
+ .. code-tab:: gdscript GDScript
|
|
|
+
|
|
|
+ extends MeshInstance3D
|
|
|
+
|
|
|
+ func _process(delta):
|
|
|
+
|
|
|
+ # Clean up before drawing.
|
|
|
+ mesh.clear_surfaces()
|
|
|
+
|
|
|
+ # Begin draw.
|
|
|
+ mesh.surface_begin(Mesh.PRIMITIVE_TRIANGLES)
|
|
|
+
|
|
|
+ # Draw mesh.
|
|
|
+
|
|
|
+ # End drawing.
|
|
|
+ mesh.surface_end()
|
|
|
+
|
|
|
+The above code will dynamically create and draw a single surface each frame.
|