diff --git a/tutorials/3d/procedural_geometry/arraymesh.rst b/tutorials/3d/procedural_geometry/arraymesh.rst index ba21a5b3d..7225b1984 100644 --- a/tutorials/3d/procedural_geometry/arraymesh.rst +++ b/tutorials/3d/procedural_geometry/arraymesh.rst @@ -92,6 +92,10 @@ Under ``_ready()``, create a new Array. .. code-tab:: gdscript GDScript var surface_array = [] + + .. code-tab:: csharp C# + + var surfaceArray = new Godot.Collections.Array(); This will be the array that we keep our surface information in - it will hold all the arrays of data that the surface needs. Godot will expect it to be of @@ -102,6 +106,11 @@ size ``Mesh.ARRAY_MAX``, so resize it accordingly. var surface_array = [] surface_array.resize(Mesh.ARRAY_MAX) + + .. code-tab:: csharp C# + + var surfaceArray = new Godot.Collections.Array(); + surfaceArray.Resize((int)Mesh.ArrayType.Max); Next create the arrays for each data type you will use. @@ -113,6 +122,13 @@ Next create the arrays for each data type you will use. var normals = PackedVector3Array() var indices = PackedInt32Array() + .. code-tab:: csharp C# + + var verts = new List(); + var uvs = new List(); + var normals = new List(); + var indices = new List(); + Once you have filled your data arrays with your geometry you can create a mesh by adding each array to ``surface_array`` and then committing to the mesh. @@ -124,7 +140,22 @@ by adding each array to ``surface_array`` and then committing to the mesh. surface_array[Mesh.ARRAY_NORMAL] = normals surface_array[Mesh.ARRAY_INDEX] = indices - mesh.add_surface_from_arrays(Mesh.PRIMITIVE_TRIANGLES, surface_array) # No blendshapes, lods, or compression used. + # No blendshapes, lods, or compression used. + mesh.add_surface_from_arrays(Mesh.PRIMITIVE_TRIANGLES, surface_array) + + .. code-tab:: csharp C# + + surfaceArray[(int)Mesh.ArrayType.Vertex] = verts.ToArray(); + surfaceArray[(int)Mesh.ArrayType.TexUV] = uvs.ToArray(); + surfaceArray[(int)Mesh.ArrayType.Normal] = normals.ToArray(); + surfaceArray[(int)Mesh.ArrayType.Index] = indices.ToArray(); + + var arrMesh = Mesh as ArrayMesh; + if (arrMesh != null) + { + // No blendshapes, lods, or compression used. + arrMesh.AddSurfaceFromArrays(Mesh.PrimitiveType.Triangles, surfaceArray); + } .. note:: In this example, we used ``Mesh.PRIMITIVE_TRIANGLES``, but you can use any primitive type available from mesh. @@ -157,7 +188,43 @@ Put together, the full code looks like: surface_array[Mesh.ARRAY_INDEX] = indices # Create mesh surface from mesh array. - mesh.add_surface_from_arrays(Mesh.PRIMITIVE_TRIANGLES, surface_array) # No blendshapes, lods, or compression used. + # No blendshapes, lods, or compression used. + mesh.add_surface_from_arrays(Mesh.PRIMITIVE_TRIANGLES, surface_array) + + .. code-tab:: csharp C# + + public partial class MyMeshInstance3D : MeshInstance3D + { + public override void _Ready() + { + var surfaceArray = new Godot.Collections.Array(); + surfaceArray.Resize((int)Mesh.ArrayType.Max); + + // C# arrays cannot be resized or expanded, so use Lists to create geometry. + var verts = new List(); + var uvs = new List(); + var normals = new List(); + var indices = new List(); + + /*********************************** + * Insert code here to generate mesh. + * *********************************/ + + // Convert Lists to arrays and assign to surface array + surfaceArray[(int)Mesh.ArrayType.Vertex] = verts.ToArray(); + surfaceArray[(int)Mesh.ArrayType.TexUV] = uvs.ToArray(); + surfaceArray[(int)Mesh.ArrayType.Normal] = normals.ToArray(); + surfaceArray[(int)Mesh.ArrayType.Index] = indices.ToArray(); + + var arrMesh = Mesh as ArrayMesh; + if (arrMesh != null) + { + // Create mesh surface from mesh array + // No blendshapes, lods, or compression used. + arrMesh.AddSurfaceFromArrays(Mesh.PrimitiveType.Triangles, surfaceArray); + } + } + } The code that goes in the middle can be whatever you want. Below we will present some @@ -180,7 +247,6 @@ that you find online. var rings = 50 var radial_segments = 50 - var height = 1 var radius = 1 func _ready(): @@ -233,6 +299,74 @@ that you find online. # Insert committing to the ArrayMesh here. + .. code-tab:: csharp C# + + public partial class MyMeshInstance3D : MeshInstance3D + { + private int _rings = 50; + private int _radialSegments = 50; + private float _radius = 1; + + public override void _Ready() + { + // Insert setting up the surface array and lists here. + + // Vertex indices. + var thisRow = 0; + var prevRow = 0; + var point = 0; + + // Loop over rings. + for (var i = 0; i < _rings + 1; i++) + { + var v = ((float)i) / _rings; + var w = Mathf.Sin(Mathf.Pi * v); + var y = Mathf.Cos(Mathf.Pi * v); + + // Loop over segments in ring. + for (var j = 0; j < _radialSegments; j++) + { + var u = ((float)j) / _radialSegments; + var x = Mathf.Sin(u * Mathf.Pi * 2); + var z = Mathf.Cos(u * Mathf.Pi * 2); + var vert = new Vector3(x * _radius * w, y, z * _radius * w); + verts.Add(vert); + normals.Add(vert.Normalized()); + uvs.Add(new Vector2(u, v)); + point += 1; + + // Create triangles in ring using indices. + if (i > 0 && j > 0) + { + indices.Add(prevRow + j - 1); + indices.Add(prevRow + j); + indices.Add(thisRow + j - 1); + + indices.Add(prevRow + j); + indices.Add(thisRow + j); + indices.Add(thisRow + j - 1); + } + } + + if (i > 0) + { + indices.Add(prevRow + _radialSegments - 1); + indices.Add(prevRow); + indices.Add(thisRow + _radialSegments - 1); + + indices.Add(prevRow); + indices.Add(prevRow + _radialSegments); + indices.Add(thisRow + _radialSegments - 1); + } + + prevRow = thisRow; + thisRow = point; + } + + // Insert committing to the ArrayMesh here. + } + } + Saving ------ @@ -244,3 +378,8 @@ This is useful when you want to generate a mesh and then use it later without ha # Saves mesh to a .tres file with compression enabled. ResourceSaver.save(mesh, "res://sphere.tres", ResourceSaver.FLAG_COMPRESS) + + .. code-tab:: csharp C# + + // Saves mesh to a .tres file with compression enabled. + ResourceSaver.Save(Mesh, "res://sphere.tres", ResourceSaver.SaverFlags.Compress);