-
-
Notifications
You must be signed in to change notification settings - Fork 3.5k
Description
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)