Get UVs from mesh at a give Vector3 without using a raycaster

Hello everyone,
I am having a mesh with an applied texture on it and want to get the UV values at a given point (given as a Vector3). It is asserted, that the point lies on the mesh.
My initial idea was to use a raycaster, which raycasts the mesh through the point and the intersection at that point has the uv value. But is there an other possibility to get the uv values at that point without te usage of a raycaster?

3JS Raycaster uses the same method to calculate the uv coordinates of given point on mesh, as the rest of the world does.

To do this, you need the index of the face that target point resides on.
Basically, you need to convert the target point coordinate from Cartesian to Barycentric.
Then using the corresponding uv coords for three vertices, convert target point from Barycentric to UV coordinates.

Anyway, having the coords for target point is not enough, you also need the face index.

1 Like

I might be wrong here since I only needed position and normal in related cases (altering geometry to create terrain that works with Raycaster), but doesn’t (buffer)geometry.getAttribute(“uv”) and similar approaches, e.g. uv.fromBufferAttribute(destinationuvvariable, index) get the UV at a given point? Don’t know about conversions that might be needed afterwards, but it’s a way that doesn’t involve Raycaster, after all…

EDIT: My bad, didn’t pay attention to the requirement of passing a Vector3 to get the UV value, so I guess this possibility doesn’t meet the desired criterion.

So if I have an indexed Buffered Geometry, I can access the face via the indexed positions. But how are the uvs in the uv-Bufferedattribute stored? Is every attribute then indexed or only the positions?
If I understood you correctly @Yin_Cognyto and @rrrr_rrrr I could access the face with the positions and then access the uvs from the buffered attributes?


index = bufferedAttribute("index)
positions = bufferedAttribute("position")
uv = bufferedAttribute("uv")
for (let index = 0; index < indices.length; index += 3) { 
let a = new Vector3(positions[indices[index] * 3], positions[indices[index] * 3 + 1], positions[indices[index] * 3 + 2])
let b = ... //second triangle corner
let c = ... // third triangle corner 

**let uv_a = ???** // how do I access the uv for the a triangle corner from the uv array? 


I hope the pseudocode example made clear, what I am trying to achieve.

I’ll let more experienced folks to point out the essential details when it comes to Three.js (since I didn’t work with the UVs as a BufferAttribute just yet), so I’ll try to provide some additional information to what @rrrr_rrrr said, regarding the cartesian / barycentric / uv coordinates. See here, here, here, here or here to get an idea about all that.

As for how the uvs are structured in Three.js, they are basically an array of [0…1] interval values, where a pair of such values represent the (u, v) coordinates for the vertices - at least that’s how I understood them to be. For example, the top left vertex of a plane would have the uvs of (0, 0) as the top left corner, the bottom right vertex of it would have the uvs of (1, 1) as the bottom right corner. To get or set them, see the examples here or here.

When it comes to faces, their index and a Vector3 point on such a face, to my (still not at an expert level) knowledge, a face is outlined by the 3 vertices (and their x, y, z coordinates) that represent the corners of that face’s triangle and identified also by that face’s normal (i.e. the direction of the face). So, at a rudimentary level, I guess that iterating through sets of 3 vertices and their (x, y, z) position and then checking if the given point belongs to the triangle made by those 3 vertices using a method similar to Triangle.containsPoint() - or, even better, directly get the uv of that point in the triangle via Triangle.getUV - should get you closer to your objective. Bear in mind that the Three.js Triangle also has some potentially useful methods related to what @rrrr_rrrr said, i.e. Triangle.getBarycoord, so maybe you can make use of those as well.


PlaneBufferGeometry.html (2.3 KB)