arraymesh.rst 7.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219
  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 is the ``PrimitiveType``, this is an OpenGL concept that instructs the GPU
  8. how to arrange the primitive based on the vertices given whether it is triangles,
  9. lines, points, etc. A complete list can be found under the :ref:`Mesh <class_mesh>`
  10. class reference page.
  11. The second is the actual Array that stores the mesh information. The array is a normal Godot array that
  12. is constructed with empty brackets ``[]``. It stores a ``Pool**Array`` (e.g. PoolVector3Array,
  13. PoolIntArray, etc.) for each type of information.
  14. - ``ARRAY_VERTEX`` = 0 | PoolVector3Array or PoolVector2Array
  15. - ``ARRAY_NORMAL`` = 1 | PoolVector3Array
  16. - ``ARRAY_TANGENT`` = 2 | PoolRealArray of groups of 4 floats. first 3 floats determine the tangent, and
  17. the last the binormal direction as -1 or 1.
  18. - ``ARRAY_COLOR`` = 3 | PoolColorArray
  19. - ``ARRAY_TEX_UV`` = 4 | PoolVector2Array or PoolVector3Array
  20. - ``ARRAY_TEX_UV2`` = 5 | PoolVector2Array or PoolVector3Array
  21. - ``ARRAY_BONES`` = 6 | PoolRealArray of groups of 4 floats or PoolIntArray of groups of 4 ints
  22. - ``ARRAY_WEIGHTS`` = 7 | PoolRealArray of groups of 4 floats
  23. - ``ARRAY_INDEX`` = 8 | PoolIntArray
  24. The Array of vertices is always required. All the others are optional and will only be used if included.
  25. Each array needs to have the same number of elements as the vertex array except for the index array.
  26. For arrays like tangents, an element is a group of 4 floats. So the array size will be four times
  27. the size of the vertex array size, but they will have the same number of elements
  28. The index array is unique.
  29. The third parameter is an array of blendshapes for the Mesh to use. While this tutorial does not cover
  30. using blendshapes, it is possible to specify them when creating a surface from arrays.
  31. The last parameter is the compress flags which specifies which arrays to store with half as many bits. The
  32. values can be found in the classref for :ref:`VisualServer <class_visualserver>` under :ref:`ArrayFormat <enum_visualserver_arrayformat>`.
  33. For normal usage you will find it is best to leave the last two parameters empty.
  34. ArrayMesh
  35. ---------
  36. Add an :ref:`ArrayMesh <class_arraymesh>` to a MeshInstance. Normally, adding an ArrayMesh in
  37. the editor is not useful, but in this case it allows as to access the ArrayMesh from code
  38. without creating one.
  39. Next, add a script to the MeshInstance.
  40. Under ``_ready()``, create a new Array.
  41. .. tabs::
  42. .. code-tab:: gdscript GDScript
  43. var arr = []
  44. This will be the array that we keep our surface information in, it will hold
  45. all the arrays of data that the surface needs. Godot will expect it to be of
  46. size ``Mesh.ARRAY_MAX``, so resize it accordingly.
  47. .. tabs::
  48. .. code-tab:: gdscript GDScript
  49. var arr = []
  50. arr.resize(Mesh.ARRAY_MAX)
  51. Next create the arrays for each data type you will use.
  52. .. tabs::
  53. .. code-tab:: gdscript GDScript
  54. var verts = PoolVector3Array()
  55. var uvs = PoolVector2Array()
  56. var normals = PoolVector3Array()
  57. var indices = PoolIntArray()
  58. Once you have filled your data arrays with your geometry you can create a mesh
  59. by adding each array to ``surface_array`` and then committing to the mesh.
  60. .. tabs::
  61. .. code-tab:: gdscript GDScript
  62. arr[Mesh.ARRAY_VERTEX] = verts
  63. arr[Mesh.ARRAY_TEX_UV] = uvs
  64. arr[Mesh.ARRAY_NORMAL] = normals
  65. arr[Mesh.ARRAY_INDEX] = indices
  66. mesh.add_surface_from_arrays(Mesh.PRIMITIVE_TRIANGLES, arr) # No blendshapes or compression used.
  67. .. note:: In this example, we used ``Mesh.PRIMITIVE_TRIANGLES``, but you can use any primitive type
  68. available from mesh.
  69. Put together the full code looks like:
  70. .. tabs::
  71. .. code-tab:: gdscript GDScript
  72. extends MeshInstance
  73. func _ready():
  74. var arr = []
  75. arr.resize(Mesh.ARRAY_MAX)
  76. # PoolVectorXXArrays for mesh construction.
  77. var verts = PoolVector3Array()
  78. var uvs = PoolVector2Array()
  79. var normals = PoolVector3Array()
  80. var indices = PoolIntArray()
  81. #######################################
  82. ## Insert code here to generate mesh ##
  83. #######################################
  84. # Assign arrays to mesh array.
  85. arr[Mesh.ARRAY_VERTEX] = verts
  86. arr[Mesh.ARRAY_TEX_UV] = uvs
  87. arr[Mesh.ARRAY_NORMAL] = normals
  88. arr[Mesh.ARRAY_INDEX] = indices
  89. # Create mesh surface from mesh array.
  90. mesh.add_surface_from_arrays(Mesh.PRIMITIVE_TRIANGLES, arr) # No blendshapes or compression used.
  91. The code that goes in the middle can be whatever you want. Below we will present some example code that
  92. could go in the middle.
  93. Generating geometry
  94. -------------------
  95. Here is sample code for generating a sphere. Although the code is presented in
  96. GDScript, there is nothing Godot specific about the approach to generating it.
  97. This implementation has nothing in particular to do with ArrayMeshes and is just a
  98. generic approach to generating a sphere. If you are having trouble understanding it
  99. or want to learn more about procedural geometry in general, you can use any tutorial
  100. that you find online.
  101. .. tabs::
  102. .. code-tab:: gdscript GDScript
  103. extends MeshInstance
  104. var rings = 50
  105. var radial_segments = 50
  106. var height = 1
  107. var radius = 1
  108. func _ready():
  109. # Set up the PoolVectorXArrays.
  110. # Vertex indices.
  111. var thisrow = 0
  112. var prevrow = 0
  113. var point = 0
  114. # Loop over rings.
  115. for i in range(rings + 1):
  116. var v = float(i) / rings
  117. var w = sin(PI * v)
  118. var y = cos(PI * v)
  119. # Loop over segments in ring.
  120. for j in range(radial_segments):
  121. var u = float(j) / radial_segments
  122. var x = sin(u * PI * 2.0)
  123. var z = cos(u * PI * 2.0)
  124. var vert = Vector3(x * radius * w, y, z * radius * w)
  125. verts.append(vert)
  126. normals.append(vert.normalized())
  127. uvs.append(Vector2(u, v))
  128. point += 1
  129. # Create triangles in ring using indices.
  130. if i > 0 and j > 0:
  131. indices.append(prevrow + j - 1)
  132. indices.append(prevrow + j)
  133. indices.append(thisrow + j - 1)
  134. indices.append(prevrow + j)
  135. indices.append(thisrow + j)
  136. indices.append(thisrow + j - 1)
  137. if i > 0:
  138. indices.append(prevrow + radial_segments - 1)
  139. indices.append(prevrow)
  140. indices.append(thisrow + radial_segments - 1)
  141. indices.append(prevrow)
  142. indices.append(prevrow + radial_segments)
  143. indices.append(thisrow + radial_segments - 1)
  144. prevrow = thisrow
  145. thisrow = point
  146. # Commit to the ArrayMesh.
  147. Combined with the code above, this code will generate a sphere.
  148. When it comes to generating geometry with the ArrayMesh you need to understand what goes
  149. in each array and then you can follow tutorials for any language/engine and convert it into Godot.
  150. Saving
  151. ------
  152. Finally, Godot provides a single method to save ArrayMeshes using the :ref:`ResourceSaver <class_resourcesaver>`
  153. class. This is useful when you want to generate a mesh and then use it later without having to re-generate.
  154. .. tabs::
  155. .. code-tab:: gdscript GDScript
  156. # Saves mesh to a .tres file with compression enabled.
  157. ResourceSaver.save("res://sphere.tres", mesh, 32)