Search code examples
pythonmaya

Getting rotation with the distanceDimension in maya with Python


I am making a script where I can place 2 locators and between the 2 locators I am making a light.

At this moment I can make 2 locators when I click in the viewport , and it makes a light with the same distance and position.

(For getting the distance between the two locators, I use the DistanceDimension command)

But I also need the same rotation. So I need to rotate my light as well when loc1 is higher than loc2, but I don't know how to do this.

Can someone help me please? Here is a screenshot of the viewport:

https://i.sstatic.net/5MAWC.jpg

My code :

import maya.cmds as cmds


def dragger_onPress():
    pos = cmds.draggerContext(draggerContextName, query = True, anchorPoint 
= True)


    #make locator for distance
    cmds.spaceLocator(name=('DistnaceLoc'))
    cmds.move(pos[0],pos[1],pos[2])

    if cmds.objExists('DistnaceLoc') and cmds.objExists('DistnaceLoc1'):
        posLoc1_X = cmds.getAttr('DistnaceLoc.translateX')
        posLoc1_Y = cmds.getAttr('DistnaceLoc.translateY')
        posLoc1_Z = cmds.getAttr('DistnaceLoc.translateZ')

        posLoc2_X = cmds.getAttr('DistnaceLoc1.translateX')
        posLoc2_Y = cmds.getAttr('DistnaceLoc1.translateY')
        posLoc2_Z = cmds.getAttr('DistnaceLoc1.translateZ')


        Distance = cmds.distanceDimension(startPoint= 
[posLoc1_X,posLoc1_Y,posLoc1_Z],endPoint=[posLoc2_X,posLoc2_Y,posLoc2_Z])

        DistanceValue = cmds.getAttr(Distance + '.distance')
        print(DistanceValue)

        averagePosX = (posLoc1_X+posLoc2_X)/2
        averagePosY = (posLoc1_Y+posLoc2_Y)/2
        averagePosZ = (posLoc1_Z+posLoc2_Z)/2



        #create light
        lights.append(cmds.shadingNode('aiAreaLight', asLight=True))
        cmds.move(averagePosX,averagePosY,averagePosZ)
        cmds.scale((DistanceValue/2),0.1,1)

        cmds.delete('DistnaceLoc','DistnaceLoc1')




# for getting the mousepoitionw
if (cmds.contextInfo(draggerContextName, exists = True)):
    cmds.deleteUI(draggerContextName, toolContext = True )

cmds.draggerContext(draggerContextName, pressCommand = dragger_onPress2,cursor = "crossHair", space="world",snapping=True)
cmds.setToolTo(draggerContextName)

Solution

  • You'll probably find this easier to do with animation constraints rather than doing it with math. You would point-constrain the light to both locators at equal weight -- that will place it halfway between them. Then aim-constrain it to point at one of them with the world up as the 'side vector' and a rotation offset to keep the light from flipping (it's an area light, yes?)

    def area_light_between(target1, target2):
        lightShape = cmds.createNode('areaLight')
        lightXform = cmds.listRelatives(lightShape, p=True)
    
        #You can get the distance manually without creating a distance dimension:
        start = cmds.xform(target1, q=True, t=True)
        end = cmds.xform(target2, q=True, t=True)
        difference = [end[k] - start[k] for k in range(3)] 
        distance = math.sqrt(difference[0]**2 + difference[1]**2 +  difference[2]**2) 
        cmds.xform(lightXform, s = (distance / 2.0, 0.1, 1))
    
    
        # constrain the light between the targets
        # use the mo=False flag so you don't keep the offset
        cmds.pointConstraint(target1, target2,lightXform,  mo = False)
    
        # add the aim constraint (your world-up vector may vary)
        cmds.aimConstraint(target2, lightXform, worldUpVector = (0,0,1), aimVector=(1,0,0), upVector = (0,0,1), mo = False) 
    
        return lightXform
    
    area_light_between('pSphere1', 'pSphere2')
    

    My scene is Z-Up so I have to specify a world up vector of (0,0,1) -- if you're using vanilla Maya Y-up your worldUpVector will be (0,1,0). As with any aim constraint situation you'll get flipping if the aim vector gets too close to the up vector -- you'll have to handle that if you do it this way or with pure math.

    One nice advantage of this is that you can edit the constraints after the fact to offset the position or aim while retaining the overall relationship.