Godot Version
v4.7.2.stable.steam [ed1daf0bf]
Question
Hi! Relatively novice programmer here and new to the godot forums (hi!!). I have been trying to create a quick procedural voxel terrain visualiser to help me play with noise parameters in a sandbox separate from my main game.
I’m creating a 3d array of boolean block/air values and will be populating that with the noise function eventually. currently it just assigns a random value to each terrain_array[i][j][k] index.
The problem is with MultiMeshInstance3D. while I seem to be able to generate a number of instances equal to the number of true values in the 3d array, it seems that im unable to set their transforms individually with set_instance_transform(). As far as i can tell, every instance is moving to this position each time i update it. When i run my script, every cube ends up in the final index in 3d space.
The exact same code works fine when just spawning regular meshinstances as children at each array index converted to a coordinate. I don’t know what im doing wrong and i need help!!
extends Node3D
@export var block_mdl: Mesh
@export var mesh_material: Material
@export var cam: Node3D
var terrain_width: int = 32
var terrain_height: int = 16
var terrain_mesh: MultiMeshInstance3D = MultiMeshInstance3D.new()
var block_multimesh: MultiMesh = MultiMesh.new()
var terrain_array: Array
var stone_air: bool = true
func _ready() -> void:
arraygen()
meshgen()
position_camera()
func arraygen():
terrain_array.resize(terrain_width)
for i in terrain_array.size():
var z_array: Array
z_array.resize(terrain_width)
for j in z_array.size():
var y_array: Array
y_array.resize(terrain_height)
for k in y_array.size():
stone_air = randi_range(-1,0)
y_array.set(k,stone_air)
z_array.set(j,y_array)
terrain_array.set(i,z_array)
##Meshing function, iterates through 3d noise array and creates an instance at every true index's 3d position
func meshgen():
block_mdl.surface_set_material(0,mesh_material)
block_multimesh.mesh = block_mdl
block_multimesh.transform_format = MultiMesh.TRANSFORM_3D
for i in terrain_width-1:
for j in terrain_width-1:
for k in terrain_height-1:
if terrain_array[i][j][k] == true:
block_multimesh.instance_count = block_multimesh.instance_count+1
var instance_transform: Transform3D = Transform3D.IDENTITY.translated(Vector3(i,k,j))
block_multimesh.set_instance_transform(block_multimesh.instance_count-1, instance_transform)
terrain_mesh.set_multimesh(block_multimesh)
add_child(terrain_mesh)
##Duplicate test function using regular mesh instances as nodes
func meshgen_slow():
block_mdl.surface_set_material(0,mesh_material)
for i in terrain_width-1:
for j in terrain_width-1:
for k in terrain_height-1:
if terrain_array[i][j][k] == true:
var block_inst: MeshInstance3D = MeshInstance3D.new()
block_inst.mesh = block_mdl
block_inst.position = Vector3(i,k,j)
add_child(block_inst)
func position_camera():
cam.position = Vector3(terrain_width/2,terrain_height+32,-terrain_width)
cam.rotate(Vector3.UP,deg_to_rad(180))
the result of meshgen():
and the result of meshgen_slow():


