arraymesh.rst 8.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245
  1. .. _doc_arraymesh:
  2. Using the ArrayMesh
  3. ===================
  4. This tutorial will present the basics of using an :ref:`ArrayMesh <class_arraymesh>`.
  5. To do so, we will use the function :ref:`add_surface_from_arrays() <class_ArrayMesh_method_add_surface_from_arrays>`,
  6. which takes up to four parameters. The first two are required, while the second two are optional.
  7. The first parameter is the ``PrimitiveType``, an OpenGL concept that instructs the GPU
  8. how to arrange the primitive based on the vertices given, i.e. whether they represent triangles,
  9. lines, points, etc. See :ref:`Mesh.PrimitiveType <enum_Mesh_PrimitiveType>` for the options available.
  10. The second parameter, ``arrays``, is the actual Array that stores the mesh information. The array is a
  11. normal Godot array that is constructed with empty brackets ``[]``. It stores a ``Pool**Array``
  12. (e.g. PoolVector3Array, PoolIntArray, etc.) for each type of information that will be used to build the surface.
  13. The possible elements of ``arrays`` are listed below, together with the position they must have within ``arrays``.
  14. See also :ref:`Mesh.ArrayType <enum_Mesh_ArrayType>`.
  15. .. list-table::
  16. :class: wrap-normal
  17. :width: 100%
  18. :widths: auto
  19. :header-rows: 1
  20. * - Index
  21. - Mesh.ArrayType Enum
  22. - Array type
  23. * - 0
  24. - ``ARRAY_VERTEX``
  25. - :ref:`PoolVector3Array <class_PoolVector3Array>` or :ref:`PoolVector2Array <class_PoolVector2Array>`
  26. * - 1
  27. - ``ARRAY_NORMAL``
  28. - :ref:`PoolVector3Array <class_PoolVector3Array>`
  29. * - 2
  30. - ``ARRAY_TANGENT``
  31. - :ref:`PoolRealArray <class_PoolRealArray>` of groups of 4 floats. First 3 floats determine the tangent, and
  32. the last the binormal direction as -1 or 1.
  33. * - 3
  34. - ``ARRAY_COLOR``
  35. - :ref:`PoolColorArray <class_PoolColorArray>`
  36. * - 4
  37. - ``ARRAY_TEX_UV``
  38. - :ref:`PoolVector2Array <class_PoolVector2Array>` or :ref:`PoolVector3Array <class_PoolVector3Array>`
  39. * - 5
  40. - ``ARRAY_TEX_UV2``
  41. - :ref:`PoolVector2Array <class_PoolVector2Array>` or :ref:`PoolVector3Array <class_PoolVector3Array>`
  42. * - 6
  43. - ``ARRAY_BONES``
  44. - :ref:`PoolRealArray <class_PoolRealArray>` of groups of 4 floats or :ref:`PoolIntArray <class_PoolIntArray>` of groups of 4 ints. Each group lists indexes of 4 bones that affects a given vertex.
  45. * - 7
  46. - ``ARRAY_WEIGHTS``
  47. - :ref:`PoolRealArray <class_PoolRealArray>` of groups of 4 floats. Each float lists the amount of weight an determined bone on ``ARRAY_BONES`` has on a given vertex.
  48. * - 8
  49. - ``ARRAY_INDEX``
  50. - :ref:`PoolIntArray <class_PoolIntArray>`
  51. The array of vertices (at index 0) is always required. The index array is optional and will only be used if included. We won't use it in this tutorial.
  52. All the other arrays carry information about the vertices. They are also optional and will only be used if included. Some of these arrays (e.g. ``ARRAY_COLOR``)
  53. use one entry per vertex to provide extra information about vertices. They must have the same size as the vertex array. Other arrays (e.g. ``ARRAY_TANGENT``) use
  54. four entries to describe a single vertex. These must be exactly four times larger than the vertex array.
  55. For normal usage, the last two parameters in :ref:`add_surface_from_arrays() <class_arraymesh_method_add_surface_from_arrays>` are typically left empty.
  56. ArrayMesh
  57. ---------
  58. In the editor, create a :ref:`MeshInstance <class_meshinstance>` and add an :ref:`ArrayMesh <class_arraymesh>` to it in the Inspector.
  59. Normally, adding an ArrayMesh in the editor is not useful, but in this case it allows us to access the ArrayMesh
  60. from code without creating one.
  61. Next, add a script to the MeshInstance.
  62. Under ``_ready()``, create a new Array.
  63. .. tabs::
  64. .. code-tab:: gdscript GDScript
  65. var surface_array = []
  66. This will be the array that we keep our surface information in - it will hold
  67. all the arrays of data that the surface needs. Godot will expect it to be of
  68. size ``Mesh.ARRAY_MAX``, so resize it accordingly.
  69. .. tabs::
  70. .. code-tab:: gdscript GDScript
  71. var surface_array = []
  72. surface_array.resize(Mesh.ARRAY_MAX)
  73. Next create the arrays for each data type you will use.
  74. .. tabs::
  75. .. code-tab:: gdscript GDScript
  76. var verts = PoolVector3Array()
  77. var uvs = PoolVector2Array()
  78. var normals = PoolVector3Array()
  79. var indices = PoolIntArray()
  80. Once you have filled your data arrays with your geometry you can create a mesh
  81. by adding each array to ``surface_array`` and then committing to the mesh.
  82. .. tabs::
  83. .. code-tab:: gdscript GDScript
  84. surface_array[Mesh.ARRAY_VERTEX] = verts
  85. surface_array[Mesh.ARRAY_TEX_UV] = uvs
  86. surface_array[Mesh.ARRAY_NORMAL] = normals
  87. surface_array[Mesh.ARRAY_INDEX] = indices
  88. mesh.add_surface_from_arrays(Mesh.PRIMITIVE_TRIANGLES, surface_array) # No blendshapes or compression used.
  89. .. note:: In this example, we used ``Mesh.PRIMITIVE_TRIANGLES``, but you can use any primitive type
  90. available from mesh.
  91. Put together, the full code looks like:
  92. .. tabs::
  93. .. code-tab:: gdscript GDScript
  94. extends MeshInstance
  95. func _ready():
  96. var surface_array= []
  97. surface_array.resize(Mesh.ARRAY_MAX)
  98. # PoolVector**Arrays for mesh construction.
  99. var verts = PoolVector3Array()
  100. var uvs = PoolVector2Array()
  101. var normals = PoolVector3Array()
  102. var indices = PoolIntArray()
  103. #######################################
  104. ## Insert code here to generate mesh ##
  105. #######################################
  106. # Assign arrays to mesh array.
  107. surface_array[Mesh.ARRAY_VERTEX] = verts
  108. surface_array[Mesh.ARRAY_TEX_UV] = uvs
  109. surface_array[Mesh.ARRAY_NORMAL] = normals
  110. surface_array[Mesh.ARRAY_INDEX] = indices
  111. # Create mesh surface from mesh array.
  112. mesh.add_surface_from_arrays(Mesh.PRIMITIVE_TRIANGLES, surface_array) # No blendshapes or compression used.
  113. The code that goes in the middle can be whatever you want. Below we will present some example code
  114. for generating a sphere.
  115. Generating geometry
  116. -------------------
  117. Here is sample code for generating a sphere. Although the code is presented in
  118. GDScript, there is nothing Godot specific about the approach to generating it.
  119. This implementation has nothing in particular to do with ArrayMeshes and is just a
  120. generic approach to generating a sphere. If you are having trouble understanding it
  121. or want to learn more about procedural geometry in general, you can use any tutorial
  122. that you find online.
  123. .. tabs::
  124. .. code-tab:: gdscript GDScript
  125. extends MeshInstance
  126. var rings = 50
  127. var radial_segments = 50
  128. var height = 1
  129. var radius = 1
  130. func _ready():
  131. # Insert setting up the PoolVector**Arrays here.
  132. # Vertex indices.
  133. var thisrow = 0
  134. var prevrow = 0
  135. var point = 0
  136. # Loop over rings.
  137. for i in range(rings + 1):
  138. var v = float(i) / rings
  139. var w = sin(PI * v)
  140. var y = cos(PI * v)
  141. # Loop over segments in ring.
  142. for j in range(radial_segments):
  143. var u = float(j) / radial_segments
  144. var x = sin(u * PI * 2.0)
  145. var z = cos(u * PI * 2.0)
  146. var vert = Vector3(x * radius * w, y, z * radius * w)
  147. verts.append(vert)
  148. normals.append(vert.normalized())
  149. uvs.append(Vector2(u, v))
  150. point += 1
  151. # Create triangles in ring using indices.
  152. if i > 0 and j > 0:
  153. indices.append(prevrow + j - 1)
  154. indices.append(prevrow + j)
  155. indices.append(thisrow + j - 1)
  156. indices.append(prevrow + j)
  157. indices.append(thisrow + j)
  158. indices.append(thisrow + j - 1)
  159. if i > 0:
  160. indices.append(prevrow + radial_segments - 1)
  161. indices.append(prevrow)
  162. indices.append(thisrow + radial_segments - 1)
  163. indices.append(prevrow)
  164. indices.append(prevrow + radial_segments)
  165. indices.append(thisrow + radial_segments - 1)
  166. prevrow = thisrow
  167. thisrow = point
  168. # Insert committing to the ArrayMesh here.
  169. Saving
  170. ------
  171. Finally, we can use the :ref:`ResourceSaver <class_resourcesaver>` class to save the ArrayMesh.
  172. This is useful when you want to generate a mesh and then use it later without having to re-generate it.
  173. .. tabs::
  174. .. code-tab:: gdscript GDScript
  175. # Saves mesh to a .tres file with compression enabled.
  176. ResourceSaver.save("res://sphere.tres", mesh, ResourceSaver.FLAG_COMPRESS)