Search code examples
maya

Calculate the Normal of a vertex in maya with Python


I have a script when I make a light it points to my object. I did this with a normalConstrain. But is there any other way to do this without constrains ?

I think I need to calculate the normal of the closest vertex form my Light ? But I don't know how to do this, if someone can help me would be nice !

See Screenshot

Here is how I did the NormalConstrain :

    myNormalConstrain = cmds.normalConstraint('mySphere','myLight', aimVector = (0,0,1), worldUpType = 'scene',name='NormalConstrainToObject')

Solution

  • The easy way is to create a closestPointOnMesh node an connect it to the worldMesh attribute of your mesh. The only wrinkle is that there's a bug in Maya 2016 (not sure about others) where the normal value coming back from the node is not actually normalized if you are using units other than centimeters. Here's a function which does it:

    import maya.cmds as cmds
    import maya.api.OpenMaya as api
    
    
    def get_closest_normal(surface, x, y , z):
        node = cmds.createNode('closestPointOnMesh')
        cmds.connectAttr(surface + '.worldMesh ', node + ".inMesh")
        cmds.setAttr( node + ".inPosition", x, y, z, type='double3')
        normal = cmds.getAttr(node + ".normal")
        # there's a bug in Maya 2016 where the normal
        # is not properly normalized.  Not sure
        # if it's fixed in other years....  this
        # is the workaround
    
        result = api.MVector(*normal)
        cmds.delete(node)
        result.normalize()
        return result
    
    
    print get_closest_normal('pSphereShape1', 10, 1, 1)
    

    Instead of getting the number and deleting the node as done here, you could keep the node around and connect it's normal attribute to something for live updates. This is a fairly expensive node to update, however, so don't use that version for something like an animation rig without testing performance to be sure it's affordable