Dynamic Mesh Editing in Gdscript

Godot Version

4.4

Question

I have been trying to convert the code in C# on this thread to gdscript, but I can’t do it.

public override void _Ready(){
	var meshData = this.meshInstance3D.Mesh.SurfaceGetArrays(0);
	var positions = meshData[(int)Mesh.ArrayType.Vertex].AsVector3Array();
	GD.Print(positions.Length);
	for(var index=0;index<positions.Length;index++){
		positions[index].Y *= Mathf.Sin(positions[index].Y*50);
	}
	meshData[(int)Mesh.ArrayType.Vertex] = positions;
	var newMesh = new ArrayMesh();
	newMesh.AddSurfaceFromArrays(Mesh.PrimitiveType.Triangles,meshData);
	this.meshInstance3D.Mesh = newMesh;
}

My code can’t seem to replace the verts in the ArrayMesh. Here is what I have:

func _create_mesh_array() -> Array:
	if true: 
		var output_mesh : ArrayMesh
		output_mesh = ArrayMesh.new()

		# This makes a copy of the prim as an ArrayMesh
		output_mesh.add_surface_from_arrays(Mesh.PRIMITIVE_TRIANGLES, prim.get_mesh_arrays())

		var pos : PackedVector3Array = output_mesh.surface_get_arrays(0)[Mesh.ARRAY_VERTEX]
		print(pos)

		# This messes with the verts
		for i in range(pos.size()):
			var vert = pos[i]
			vert += Vector3(0,1,0)
			pos[i] = vert

		print(pos) # verify the verts have changed
		
		# Now struggle in vain to get it all back into the ArrayMesh...?
		output_mesh.surface_get_arrays(0)[Mesh.ARRAY_VERTEX] = pos # ?
		
		# This should return the new data - one day
		return output_mesh.surface_get_arrays(0)

Any clues?

You can’t replace values inside the Arrays like this. That will do nothing.

First, because Mesh.ARRAY_VERTEX is a PackedVectorArray which is a COW Vector array that does copy on write. You are never editing the “original” array when you assign a new value because it creates a copy on change.

Second, changing the arrays from surface_get_arrays() does nothing at all for the mesh as those are just data arrays. They have zero ties to your actual mesh, it is just data.

You need to clear the old mesh surface(s) and create a new surface with add_surface_from_arrays() using the changed arrays.

If you already know very well what you are doing and how mesh arrays function you can use the RenderingServer API to update surface regions instead of clearing and creating the entire surface but that is far more advanced and error-prone.

1 Like

Hi, thanks. How do I clear a surface by index? (I mean using ArrayMesh)

In the C# code, there’s this meshData[(int)Mesh.ArrayType.Vertex] = positions; which seems to replace the data in that array. Is this just C# magic, vs the COW you mentioned?

(Will look into the API.)

Mesh surface arrays are a normal Godot Array that is passed by reference with multiple PackedXYZArray which are all COW on the inside.

Sure when you only have one user of the array you don’t notice but if e.g. anything would use the vertices PackedVector3Array directly and you change a vertex all other users of that cow array would bail out from that change and keep their old array data copy.

You cant clear individual mesh surfaces, you either clear all or none.

The reason for this is because internally a rendering mesh is just a giant data array with a certain stride / offset so you can’t just start to stitch something randomly in the middle as it would invalidate most of the data basically requiring to recreat a new mesh anyway.

1 Like

Okay, I get your general message. I will look at the other tools in gdscript for mesh hacking. Still a bit confused by that C# code though, but meh. Can’t solve all the mysteries!

Thanks!

The docs have many confusing references to ArrayMesh, like this line:

The MeshDataTool is not as fast as altering arrays directly using ArrayMesh. From the second paragraph in Using the MeshDataTool — Godot Engine (latest) documentation in English

Is that one a bug?

I am not sure what should be confusing here. MeshDataTool is a convenience helper class to build arrays to create mesh surfaces. All convenience costs more because you pay for all the extra steps behind the scene.

The words say “altering arrays directly using ArrayMesh”. It’s not unclear, but it does seem wrong, from what you explained before.

I’m just a mesh code-editing newb right now and there’s a lot of contradicting info (like in the reference post in the OP), not angry with you or anything!

This topic was automatically closed 30 days after the last reply. New replies are no longer allowed.