[Maya] Get world-space position of a uv coordinate

There is an API function for just this expect that it requires the polygon id that the uv coordinate resides on:

getPointAtUV (int polygonId, MPoint &theClosestPoint, float2 &uvPoint, .....)
 	Return the position of the point at the given UV value in the current polygon

And I don’t know of a fast way to query that when I am looking up a uv coordinate and not an actual uv index. The only method I have come up with is to iterate over all the polygons and put that lookup in a try/except, since it will error if the uv does not exist on a given polygon.
I could also loop through all polygons and query their uvs to see if my reference point is contained within its boundaries. That actually might be the next thing I try.

Does anyone know of a better way to get the polygons associated with a uv coordinate, or even a different way of approaching this?

1 Like

I think you’re going to have to walk the geo as you describe, though the try/except thing is a pain. That function should probably return None, -1, etc. on a failure.

Don’t forget that a single UV may appear on multiple polygons.

Here’s how it could be done with pymel or maya.cmds

import pymel.core as pm

for x in pm.filterExpand(sm=35, ex=1):
    vtx = pm.polyListComponentConversion(x, fuv=1, tv=1)[0] #get vertex of uv
    worldPos = pm.PyNode(vtx).getPosition(space='world') #get world space coord of vertex

    print '{0} : {1}'.format(x, worldPos)
import maya.cmds as mc

for x in mc.filterExpand(sm=35, ex=1):
    vtx = mc.polyListComponentConversion(x, fuv=1, tv=1)[0] #get vertex of uv
    worldPos = mc.xform(vtx, q=1, t=1, ws=1) #get world space coord of vertex
    
    print '{0} : {1}'.format(x, worldPos)

That only works if you are getting the position of a uv index, like pCube.map[5]. I am trying to get the world-space position of any arbitrary u and v coordinate, like 0.43, 0.37.

I’m doing it on a fairly simple mesh that I know doesn’t have overlapping uvs, so I’m just using the try/except method listed above.

Not sure if you care about speed but what if you create a follicle?
Connect the shape.outMesh to the follicle.inputMesh and shape.worldMatrix to follicle.inputMatrix.
Connect the follicle.outTranslate to some transform and then set the UV values on the follicle node.
Then you have a worldspace position to query.
Would that work for your needs?

There’s no simple way to do this for an unconstrained case: there’s no trivial way to be sure that (a) the UV coord maps to any place on an actual surface and (b) that it maps to only one place.

You could probably do this by walking mesh triangles. Check every try to see if it’s uv bounding box contains the coord (triangles get you off the hook for topology). Get the UV coords and convert the UV to a barycenter. Then apply that barycenter as weights for the positions of the vert corners. You yield the position if it is valid (it might not be: the UV bbox is just a first approximation of the test “am i inside this triangle”) Your outer loop will have to do something with each yielded position – of which there may be none

I may try this because I’ve never done anything like and it sounds like an interesting challenge. Thanks for the ideas.

I did a quick test and it’s quite simple
[ul]
[li]Get the shape of your object
[/li][li]Create a pointOnPoly constraint (just the node, not connected to anything)
[/li][li]Plug the outMesh of the shape to the constraint’s “target[0].targetMesh” attribute
[/li][li]Use your UV coordinates to set the constraint’s “target[0].targetUV” attribute
[/li][li]Get the position by using getting the constraint’s “constraintTranslate” attribute
[/li][/ul]