Skip to content

Instantly share code, notes, and snippets.

@Woynert
Created March 14, 2024 15:37
Show Gist options
  • Select an option

  • Save Woynert/570625c853d04f336310912e27a7351e to your computer and use it in GitHub Desktop.

Select an option

Save Woynert/570625c853d04f336310912e27a7351e to your computer and use it in GitHub Desktop.
Godot: Generate navigation mesh from ArrayMeshes recursively
@tool
extends NavigationRegion3D
@export var generate: bool = false:
set(value):
_on_generate()
var _source_nodes: Array[MeshInstance3D] = []
var _final_mesh: ArrayMesh
func _on_generate():
# cleanup
_source_nodes.clear()
_final_mesh = ArrayMesh.new()
if !navigation_mesh:
printerr("E: no navigation_mesh found")
return
print("I: Generating navigation mesh")
_rec_find_mesh(self)
_generate()
print("I: Finished")
func _rec_find_mesh(node: Node):
if node is MeshInstance3D:
var mesh: Mesh = node.mesh
if mesh is ArrayMesh:
_source_nodes.append(node)
for child in node.get_children():
_rec_find_mesh(child)
func _generate():
# extract surfaces and transform vertex
for node: MeshInstance3D in _source_nodes:
if node.mesh is ArrayMesh:
_compile_mesh(node.mesh, node.global_transform)
print("I: final_mesh surfaces = %s" % _final_mesh.get_surface_count())
# set nav mesh
var navmesh = navigation_mesh
navmesh.create_from_mesh(_final_mesh)
set_navigation_mesh(null)
set_navigation_mesh(navmesh)
func _compile_mesh(array_mesh: ArrayMesh, trans: Transform3D):
var aux_mesh = ArrayMesh.new()
var copy_mesh = ArrayMesh.new()
# extract surfaces
for i in array_mesh.get_surface_count():
aux_mesh.add_surface_from_arrays(Mesh.PRIMITIVE_TRIANGLES, array_mesh.surface_get_arrays(i))
var origin_offset = trans.origin - global_position
var scale_offset = trans.basis.get_scale()
var quat_offset = trans.basis.get_rotation_quaternion().inverse()
for k in aux_mesh.get_surface_count():
var mdt = MeshDataTool.new()
mdt.create_from_surface(aux_mesh, k)
# offset each vertex
for i in range(mdt.get_vertex_count()):
mdt.set_vertex(i, (mdt.get_vertex(i) * scale_offset) * quat_offset + origin_offset)
copy_mesh.clear_surfaces()
mdt.commit_to_surface(copy_mesh)
# compile
for i in copy_mesh.get_surface_count():
_final_mesh.add_surface_from_arrays(Mesh.PRIMITIVE_TRIANGLES, copy_mesh.surface_get_arrays(i))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment