Skip to content

Instantly share code, notes, and snippets.

@apples
Created September 18, 2026 04:54
Show Gist options
  • Select an option

  • Save apples/98409ffc007dc16e0ccd3285d6d754c5 to your computer and use it in GitHub Desktop.

Select an option

Save apples/98409ffc007dc16e0ccd3285d6d754c5 to your computer and use it in GitHub Desktop.
dynamic_multi_mesh_instance_3d.gd
@tool
extends MultiMeshInstance3D
class_name DynamicMultiMeshInstance3D
## Implements dynamic add/remove methods for MultiMesh.
##
## If a slot `_id_to_index[id]` is negative, this indicates that `id` is unused,
## and the value is the *next* unused id is encoded as `-id - 2`.
## If the next unused id decodes to `-1`, then this slot is the last unused slot.
var _id_to_index: PackedInt32Array
var _index_to_id: PackedInt32Array
var _first_free_id: int = -1
func instance_count() -> int:
var vic = multimesh.visible_instance_count
return vic if vic != -1 else multimesh.instance_count
func get_instance_ids() -> PackedInt32Array:
return _index_to_id.slice(instance_count())
func add_instance(xform: Transform3D) -> int:
_ensure_capacity(instance_count() + 1)
var id: int = _first_free_id
_first_free_id = -_id_to_index[id] - 2
var index: int = multimesh.visible_instance_count
_id_to_index[id] = index
_index_to_id[index] = id
multimesh.visible_instance_count = index + 1
multimesh.set_instance_transform(index, xform)
return id
func remove_instance(id: int) -> void:
assert(id >= 0 and id < _id_to_index.size())
assert(_id_to_index[id] >= 0)
var index: int = _id_to_index[id]
_id_to_index[id] = -_first_free_id - 2
_first_free_id = id
var last_index: int = multimesh.visible_instance_count - 1
multimesh.visible_instance_count = last_index
if last_index == index:
_index_to_id[index] = -1
return
var last_id: int = _index_to_id[last_index]
multimesh.set_instance_transform(index, multimesh.get_instance_transform(last_index))
_index_to_id[index] = last_id
_index_to_id[last_index] = -1
_id_to_index[last_id] = index
func set_instance_transform(id: int, xform: Transform3D) -> void:
assert(id >= 0 and id < instance_count())
assert(_id_to_index[id] >= 0)
multimesh.set_instance_transform(_id_to_index[id], xform)
func get_instance_transform(id: int) -> Transform3D:
assert(id >= 0 and id < instance_count())
assert(_id_to_index[id] >= 0)
return multimesh.get_instance_transform(_id_to_index[id])
func _ensure_capacity(cap: int) -> void:
if multimesh.visible_instance_count == -1:
multimesh.visible_instance_count = multimesh.instance_count
cap = nearest_po2(cap)
if cap <= multimesh.instance_count:
assert(_first_free_id != -1)
return
assert(_first_free_id == -1)
_first_free_id = _id_to_index.size()
_id_to_index.resize(cap)
_index_to_id.resize(cap)
for i in range(_first_free_id, cap):
_id_to_index[i] = -i - 3
_index_to_id[i] = -1
_id_to_index[cap - 1] = -1
var buf := multimesh.buffer
multimesh.instance_count = cap
assert(multimesh.transform_format == MultiMesh.TRANSFORM_3D)
assert(!multimesh.use_colors)
assert(!multimesh.use_custom_data)
buf.resize(cap * 12)
multimesh.buffer = buf
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment