surfacetool.rst 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108
  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:`ImmediateGeometry <class_immediategeometry>` node. 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. st.add_normal() # Overwritten by normal below.
  13. st.add_normal() # Added to next vertex.
  14. st.add_color() # Added to next vertex.
  15. st.add_vertex() # Captures normal and color above.
  16. st.add_normal() # Normal never added to a vertex.
  17. When finished generating your geometry with the :ref:`SurfaceTool <class_surfacetool>`
  18. call ``commit()`` to finish generating the mesh. If an :ref:`ArrayMesh <class_ArrayMesh>` is passed
  19. to ``commit()`` then it appends a new surface to the end of the ArrayMesh. While if nothing is passed
  20. in, ``commit()`` returns an ArrayMesh.
  21. .. tabs::
  22. .. code-tab:: gdscript GDScript
  23. st.commit(mesh)
  24. # Or:
  25. var mesh = st.commit()
  26. Code creates a triangle with indices
  27. .. tabs::
  28. .. code-tab:: gdscript GDScript
  29. var st = SurfaceTool.new()
  30. st.begin(Mesh.PRIMITIVE_TRIANGLES)
  31. # Prepare attributes for add_vertex.
  32. st.add_normal(Vector3(0, 0, 1))
  33. st.add_uv(Vector2(0, 0))
  34. # Call last for each vertex, adds the above attributes.
  35. st.add_vertex(Vector3(-1, -1, 0))
  36. st.add_normal(Vector3(0, 0, 1))
  37. st.add_uv(Vector2(0, 1))
  38. st.add_vertex(Vector3(-1, 1, 0))
  39. st.add_normal(Vector3(0, 0, 1))
  40. st.add_uv(Vector2(1, 1))
  41. st.add_vertex(Vector3(1, 1, 0))
  42. # Commit to a mesh.
  43. var mesh = st.commit()
  44. You can optionally add an index array, either by calling ``add_index()`` and adding
  45. vertices to the index array or by calling ``index()`` which shrinks the vertex array
  46. to remove duplicate vertices.
  47. .. tabs::
  48. .. code-tab:: gdscript GDScript
  49. # Creates a quad from four corner vertices.
  50. # Add_index does not need to be called before add_vertex.
  51. st.add_index(0)
  52. st.add_index(1)
  53. st.add_index(2)
  54. st.add_index(1)
  55. st.add_index(3)
  56. st.add_index(2)
  57. # Alternatively:
  58. st.index()
  59. Similarly, if you have an index array, but you want each vertex to be unique (e.g. because
  60. you want to use unique normals or colors per face instead of per-vertex), you can call ``deindex()``.
  61. .. tabs::
  62. .. code-tab:: gdscript GDScript
  63. st.deindex()
  64. If you don't add custom normals yourself, you can add them using ``generate_normals()``, which should
  65. be called after generating geometry and before committing the mesh using ``commit()`` or
  66. ``commit_to_arrays()``. Calling ``generate_normals(true)`` will flip the resulting normals. As a side
  67. note, ``generate_normals()`` only works if the primitive type is set to ``Mesh.PRIMITIVE_TRIANGLES``.
  68. If you don't add custom tangents, they can be added with ``generate_tangents()``, but it requires
  69. that each vertex have UVs and normals set already.
  70. .. tabs::
  71. .. code-tab:: gdscript GDScript
  72. st.generate_normals()
  73. st.generate_tangents()
  74. By default, when generating normals, they will be calculated on a per-face basis. If you want
  75. smooth vertex normals, when adding vertices, call ``add_smooth_group()``. ``add_smooth_group()``
  76. needs to be called while building the geometry, e.g. before the call to ``add_vertex()``
  77. (if non-indexed) or ``add_index()`` (if indexed).