Skip to content

Properly document Mesh.surface_update_region #3787

@clayjohn

Description

@clayjohn

The documentation for surface_update_region() currently says not to use it because it can be quite dangerous. While that is true, it would be a lot less dangerous to use if we actually documented how it works. The benefit of surface_update_region() is that it updates the OpenGL vertex buffer array directly. This saves a lot of overhead in the VisualServer, plus you don't have to delete and re-allocate buffers every frame. Accordingly, it is the fastest way to update meshes dynamically, but it is very complex and it is easy to completely break your mesh

Here I will lay out plans for updating the documentation appropriately. This is more for me than anyone else.

First: update Mesh.surface_update_region() and the corresponding VisualServer Functions.

Next: Add a tutorial to the Procedural Geometry series using Mesh.surface_update_region(). Mesh.surface_update_region() is the fastest way to have dynamic geometry. It is used internally by softbody meshes and Sprite3Ds. But it can be a real pain to work with. The tutorial will have to outline how to access the vertex buffer properly. As well as explain how each part of the buffer changes when mesh compression settings are used (since GDScript doesn't have half_float's this section will only be useful for GDNative and maybe C#).

Below is example code for the extreme basics.

extends MeshInstance

var array
var surface_format
var vertex_len
var index_len
	
var mesh_buffer
var mesh_stride
var vertex_offset

func _ready():
	array = VisualServer.mesh_surface_get_array(mesh.get_rid(), 0)
	surface_format = VisualServer.mesh_surface_get_format(mesh.get_rid(), 0)
	vertex_len = VisualServer.mesh_surface_get_array_len(mesh.get_rid(), 0)
	index_len = VisualServer.mesh_surface_get_array_index_len(mesh.get_rid(), 0)
	
	mesh_buffer = VisualServer.mesh_surface_get_array(mesh.get_rid(), 0)
	mesh_stride = VisualServer.mesh_surface_get_format_stride(surface_format, vertex_len, index_len)
	vertex_offset = VisualServer.mesh_surface_get_format_offset(surface_format, vertex_len, index_len, VisualServer.ARRAY_VERTEX)

func _process(delta):
	var pos = get_node("../Camera").project_position(get_viewport().get_mouse_position(), 1.5)
	var a = PoolRealArray()
	a.resize(3)
	a[0] = pos.x
	a[1] = pos.y
	a[2] = pos.z
	var c = var2bytes(a)

	# Ignore the array type and the var type inside the array
	for i in range(12):
		array[vertex_offset + i] = c[i+8]
	
	VisualServer.mesh_surface_update_region(mesh.get_rid(), 0, 0, array)

Metadata

Metadata

Assignees

No one assigned

    Labels

    area:class referenceIssues and PRs about the class reference, which should be addressed on the Godot engine repositoryenhancement

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions