surfacetool.rst 6.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207
  1. .. _doc_surfacetool:
  2. Using the SurfaceTool
  3. =====================
  4. The :ref:`SurfaceTool <class_surfacetool>` provides a useful interface for constructing geometry.
  5. The interface is similar to the :ref:`ImmediateMesh <class_ImmediateMesh>` class. You
  6. set each per-vertex attribute (e.g. normal, uv, color) and then when you add a vertex it
  7. captures the attributes.
  8. The SurfaceTool also provides some useful helper functions like ``index()`` and ``generate_normals()``.
  9. Attributes are added before each vertex is added:
  10. .. tabs::
  11. .. code-tab:: gdscript GDScript
  12. var st = SurfaceTool.new()
  13. st.begin(Mesh.PRIMITIVE_TRIANGLES)
  14. st.set_normal() # Overwritten by normal below.
  15. st.set_normal() # Added to next vertex.
  16. st.set_color() # Added to next vertex.
  17. st.add_vertex() # Captures normal and color above.
  18. st.set_normal() # Normal never added to a vertex.
  19. .. code-tab:: csharp
  20. st.SetNormal(); // Overwritten by normal below.
  21. st.SetNormal(); // Added to next vertex.
  22. st.SetColor(); // Added to next vertex.
  23. st.AddVertex(); // Captures normal and color above.
  24. st.SetNormal(); // Normal never added to a vertex.
  25. When finished generating your geometry with the :ref:`SurfaceTool <class_surfacetool>`,
  26. call ``commit()`` to finish generating the mesh. If an :ref:`ArrayMesh <class_ArrayMesh>` is passed
  27. to ``commit()``, then it appends a new surface to the end of the ArrayMesh. While if nothing is passed
  28. in, ``commit()`` returns an ArrayMesh.
  29. .. tabs::
  30. .. code-tab:: gdscript GDScript
  31. # Add surface to existing ArrayMesh.
  32. st.commit(mesh)
  33. # -- Or Alternatively --
  34. # Create new ArrayMesh.
  35. var mesh = st.commit()
  36. .. code-tab:: csharp
  37. st.Commit(mesh);
  38. // Or:
  39. var mesh = st.Commit();
  40. The code below creates a triangle without indices.
  41. .. tabs::
  42. .. code-tab:: gdscript GDScript
  43. var st = SurfaceTool.new()
  44. st.begin(Mesh.PRIMITIVE_TRIANGLES)
  45. # Prepare attributes for add_vertex.
  46. st.set_normal(Vector3(0, 0, 1))
  47. st.set_uv(Vector2(0, 0))
  48. # Call last for each vertex, adds the above attributes.
  49. st.add_vertex(Vector3(-1, -1, 0))
  50. st.set_normal(Vector3(0, 0, 1))
  51. st.set_uv(Vector2(0, 1))
  52. st.add_vertex(Vector3(-1, 1, 0))
  53. st.set_normal(Vector3(0, 0, 1))
  54. st.set_uv(Vector2(1, 1))
  55. st.add_vertex(Vector3(1, 1, 0))
  56. # Commit to a mesh.
  57. var mesh = st.commit()
  58. .. code-tab:: csharp
  59. var st = new SurfaceTool();
  60. st.Begin(Mesh.PrimitiveType.Triangles);
  61. // Prepare attributes for AddVertex.
  62. st.SetNormal(new Vector3(0, 0, 1));
  63. st.SetUV(new Vector2(0, 0));
  64. // Call last for each vertex, adds the above attributes.
  65. st.AddVertex(new Vector3(-1, -1, 0));
  66. st.SetNormal(new Vector3(0, 0, 1));
  67. st.SetUV(new Vector2(0, 1));
  68. st.AddVertex(new Vector3(-1, 1, 0));
  69. st.SetNormal(new Vector3(0, 0, 1));
  70. st.SetUV(new Vector2(1, 1));
  71. st.AddVertex(new Vector3(1, 1, 0));
  72. // Commit to a mesh.
  73. var mesh = st.Commit();
  74. You can optionally add an index array, either by calling ``add_index()`` and adding
  75. vertices to the index array manually, or by calling ``index()`` once,
  76. which generates the index array automatically and
  77. shrinks the vertex array to remove duplicate vertices.
  78. .. tabs::
  79. .. code-tab:: gdscript GDScript
  80. # Suppose we have a quad defined by 6 vertices as follows
  81. st.add_vertex(Vector3(-1, 1, 0))
  82. st.add_vertex(Vector3(1, 1, 0))
  83. st.add_vertex(Vector3(-1, -1, 0))
  84. st.add_vertex(Vector3(1, 1, 0))
  85. st.add_vertex(Vector3(1, -1, 0))
  86. st.add_vertex(Vector3(-1, -1, 0))
  87. # We can make the quad more efficient by using an index array and only utilizing 4 vertices
  88. # Suppose we have a quad defined by 6 vertices as follows
  89. st.add_vertex(Vector3(-1, 1, 0))
  90. st.add_vertex(Vector3(1, 1, 0))
  91. st.add_vertex(Vector3(-1, -1, 0))
  92. st.add_vertex(Vector3(1, 1, 0))
  93. st.add_vertex(Vector3(1, -1, 0))
  94. st.add_vertex(Vector3(-1, -1, 0))
  95. # We can make the quad more efficient by using an index array and only utilizing 4 vertices
  96. # Creates a quad from four corner vertices.
  97. # add_index() can be called before or after add_vertex()
  98. # since it's not an attribute of a vertex itself.
  99. st.add_index(0)
  100. st.add_index(1)
  101. st.add_index(2)
  102. st.add_index(1)
  103. st.add_index(3)
  104. st.add_index(2)
  105. # Alternatively we can use ``st.index()`` which will create the quad for us and remove the duplicate vertices
  106. st.index()
  107. .. code-tab:: csharp
  108. // Creates a quad from four corner vertices.
  109. // AddIndex does not need to be called before AddVertex.
  110. st.AddIndex(0);
  111. st.AddIndex(1);
  112. st.AddIndex(2);
  113. st.AddIndex(1);
  114. st.AddIndex(3);
  115. st.AddIndex(2);
  116. // Alternatively:
  117. st.Index();
  118. Similarly, if you have an index array, but you want each vertex to be unique (e.g. because
  119. you want to use unique normals or colors per face instead of per-vertex), you can call ``deindex()``.
  120. .. tabs::
  121. .. code-tab:: gdscript GDScript
  122. st.deindex()
  123. .. code-tab:: csharp
  124. st.Deindex();
  125. If you don't add custom normals yourself, you can add them using ``generate_normals()``, which should
  126. be called after generating geometry and before committing the mesh using ``commit()`` or
  127. ``commit_to_arrays()``. Calling ``generate_normals(true)`` will flip the resulting normals. As a side
  128. note, ``generate_normals()`` only works if the primitive type is set to ``Mesh.PRIMITIVE_TRIANGLES``.
  129. You may notice that normal mapping or other material properties look broken on
  130. the generated mesh. This is because normal mapping **requires** the mesh to
  131. feature *tangents*, which are separate from *normals*. You can either add custom
  132. tangents manually, or generate them automatically with
  133. ``generate_tangents()``. This method requires that each vertex have UVs and
  134. normals set already.
  135. .. tabs::
  136. .. code-tab:: gdscript GDScript
  137. st.generate_normals()
  138. st.generate_tangents()
  139. st.commit(mesh)
  140. .. code-tab:: csharp
  141. st.GenerateNormals();
  142. st.GenerateTangents();
  143. By default, when generating normals, they will be calculated on a per-vertex basis (i.e. they will
  144. be "smooth normals"). If you want flat vertex normals (i.e. a single normal vector per face), when
  145. adding vertices, call ``add_smooth_group(i)`` where ``i`` is a unique number per vertex.
  146. ``add_smooth_group()`` needs to be called while building the geometry, e.g. before the call to
  147. ``add_vertex()``.