#take a position in space and return the closest uv coordinates on a mesh
#assume mesh and pos are in the same space
static func wrld_to_uv(var mesh:ArrayMesh = null, var pos:Vector3 = Vector3.ZERO):
#create MeshDataTool to read mesh data out from ArrayMesh
var mdt = MeshDataTool.new()
mdt.create_from_surface(mesh, 0)
#default nearest triangle to furthest possible position
var inf = Vector3.INF
var nearest:Triangle = Triangle.new([inf, inf, inf])
#store projected point onto nearest triangle to calculate barycentric coords later
var projected:Vector3 = inf
#loop through each face to find the nearest face that is both facing pos and encircling it
for i in mdt.get_face_count():
#first check if face is facing pos
#the dot product of the face normal and the vector from the face center to pos will be <= 0 if this is false
#face normal
var n = mdt.get_face_normal(i)
#face triangle object
var t = get_triangle(mdt, i)
t = Triangle.new(t[0], t[1])
#face center
var c = t.center()
if n.dot(pos - c) <= 0:
continue
#then project pos onto a Plane of the triangle as a new position
var p:Plane = t.plane(n)
var proj:Vector3 = p.project(pos)
#use the projected point to see if the triangle encircles it
if !t.is_surrounding(proj):
continue
if proj.distance_to(pos) < projected.distance_to(pos):
nearest = t
projected = proj
#compute barycentric coordinates of projected in nearest
#use barycentric coordinates to weight out uv coordinates
return nearest.uv(projected)