Godot Version
Godot 4.4
Question
Hey there
Recently, I’ve been playing around with generating 3D terrain with the SurfaceTool and MeshDataTool.
I’m currently at the stage where I would like to be able to modify/deform the terrain during runtime but I’m having the following issues…
Vertex Selection:
I would like to be able to select which vertices I want to modify based on a given vector3 position. My current (somewhat naive) method for doing this is by using the MeshDataTool to traverse the mesh until I find the nearest vertex to the given position. This works for the most part but runs into problems when dealing with mesh’s with vertices that are not consistently the same distance from each other.
Is there a canonical/typical way to search for vertices in 3D meshes?
Generating Collisions:
The current version of my terrain generator firsts creates the mesh data before then generating the collision data using “create_trimesh_collision”. While this is fine when initially creating the terrain, I suspect re-generating all the collisions would be an inefficient way to update the collision when deforming only a small part of the terrain.
Is there a better approach to dynamically updating collisions?
Thank you very much for reading through all that! I would really appreciate any feedback or pointers
P.S
Here is the current method I’ve been using to find vetices in my 3D meshes
static func get_nearest_index(target_mesh:MeshInstance3D,target_position: Vector3, global_space: bool = true) -> int:
# If the target postion is in global space, convert to local space
if global_space:
target_position = target_mesh.to_local(target_position)
var mdt: MeshDataTool = MeshDataTool.new()
# Load mesh data
mdt.create_from_surface(target_mesh.mesh, 0)
# Start search from the first vertex in the array
var current_index = 0
var current_distance = mdt.get_vertex(current_index).distance_to(target_position)
while true:
var nearest_index = current_index
var shortest_distance = current_distance
# Track if we find a closer vertex
var found_closer = false
# Iterate over connected edges
for edge_index in mdt.get_vertex_edges(current_index):
var vert_index_0 = mdt.get_edge_vertex(edge_index, 0)
var vert_index_1 = mdt.get_edge_vertex(edge_index, 1)
# Find the vertex that is NOT the current one (i.e., the connected vertex)
var next_index = vert_index_0 if vert_index_1 == current_index else vert_index_1
var next_distance = mdt.get_vertex(next_index).distance_to(target_position)
# If this vertex is closer, update the next step
if next_distance < shortest_distance:
nearest_index = next_index
shortest_distance = next_distance
found_closer = true
# If no closer vertex is found, stop searching
if not found_closer:
break
# Move to the newly found closest vertex
current_index = nearest_index
current_distance = shortest_distance
return current_index