Recaculate which local axis directon (or directons) closest match a world axis

Recaculate which local axis directon (or directons) closest match a world axis

Anonymous
Not applicable
430 Views
0 Replies
Message 1 of 1

Recaculate which local axis directon (or directons) closest match a world axis

Anonymous
Not applicable

So, in Maya , you have an object. In this case a Sphere


zeroPosition.png

 

It has a X axis (twist), Y axis (up), Z axis (roll). The rotation of an object directly affects the translation. The translation is the distance the object has moved from the world origin point.
The rotation directly affects the translation because of something called world and local space.


If the rotation of the local space X is 0°, to move the sphere -1 unit in world Z axis, you can simply translate it -1 in the local Z axis. This is because the local space, and world space are matching, because the object is still at its origin.
However, if the local space has been rotated 90°,to move the sphere -1 unit in world Z axis, you have to translate it +1 in the local X axis.

 

rotate90X.png

 

In Maya you can access the following information about any object:

 

Attributes.png

 

In my case I have a morph of my sphere that pushes it out in a particular direction, here is an
example of it pushing the sphere in the -X direction

 

shapeXpositive.png

 

The use of this is for simulation a drag like affect on an object. When you move, the fat on your body drags behind you, due to friction and other obvious worldly influences. So when the sphere translates in a +X world Axis, the -X direction morph would turn on, like the example above, Creation a dragging affect on the sphere, kind of like a snail. The intensity of the drag is controlled by the velocity of the object, which i have already calculated and done the math for.

 

 

from maya import cmds
from maya import mel

mesh = 'pSphere'

blendshapeNode= 'blendShape1'

vertexNumber = cmds.polyEvaluate(mesh, vertex=True)

distance = []

simTime = cmds.playbackOptions( q=True,max=True )

# for each frame

for frame in range(1,int(simTime)):
    
    distanceFrame=[]
    
    vertexStartPosition = []
    
    vertexEndPosition = []
    
    loopRange = 0
	
	# caluclate the starting position of each vtx

    for i in range(0,int(vertexNumber)):
        
        curPointStartPosition = cmds.xform( mesh+".vtx["+str(i)+"]", query=True, translation=True, worldSpace=True )
        
        vertexStartPosition.append(curPointStartPosition)
		
	# then advance a frame
        
    advanceFrame = cmds.currentTime( frame+1, edit=True )
	
	# for each vertex calculate the end position
	
	# then calulate the distance by end-starting
	
	# divide the distance by 100 to convert to meters
	
	# then divide 1 second by 24, as there are 24 frames in a second
	
	# then divide the distance in meters by the time for 1 frame
    
    for x in range(0,int(vertexNumber)):
        
        distanceXYZ = []
    
        curPointEndPosition = cmds.xform( mesh+".vtx["+str(x)+"]", query=True, translation=True, worldSpace=True )
        
        vertexEndPosition.append(curPointEndPosition)
        
        distanceCalculationX = ((vertexEndPosition[loopRange][0]-vertexStartPosition[loopRange][0])/10)/(1.00/24.00)
        
        distanceCalculationY = ((vertexEndPosition[loopRange][1]-vertexStartPosition[loopRange][1])/10)/(1.00/24.00)
        
        distanceCalculationZ = ((vertexEndPosition[loopRange][2]-vertexStartPosition[loopRange][2])/10)/(1.00/24.00)
        
        distanceXYZ.append(distanceCalculationX)
        
        distanceXYZ.append(distanceCalculationY)
        
        distanceXYZ.append(distanceCalculationZ)
        
        distanceFrame.append(distanceXYZ)
        
        loopRange=loopRange+1
        
    distance.append(distanceFrame)
	
# reset the time
  
settime = cmds.currentTime( 1, edit=True )

frameRange=0

# for each frame

for frame in range(1,int(simTime)):

    time = cmds.currentTime(query=True)
	
	# for each vertex, in each frame, set the blendshape weight of the corresponding angle, to the velocity (will probably need to remap the values to between 0-1 at some point)
    
    for i in range(0,int(vertexNumber)):
    
        # X setBlendShapes key everyFrame
    
        if distance[frameRange][i][0] > 0:
            
            cmds.setAttr(blendshapeNode+'.inputTarget[0].inputTargetGroup[0].targetWeights['+str(i)+']',distance[frameRange][i][0])
            
            mel.eval('setKeyframe '+blendshapeNode+'.inputTarget[0].inputTargetGroup[0].targetWeights['+str(i)+']')
            
        else:
            
            cmds.setAttr(blendshapeNode+'.inputTarget[0].inputTargetGroup[0].targetWeights['+str(i)+']',0.0)
            
            mel.eval('setKeyframe '+blendshapeNode+'.inputTarget[0].inputTargetGroup[0].targetWeights['+str(i)+']')
            
        
        if distance[frameRange][i][0] < 0:
            
            cmds.setAttr(blendshapeNode+'.inputTarget[0].inputTargetGroup[1].targetWeights['+str(i)+']',(-1*distance[frameRange][i][0]))
            
            mel.eval('setKeyframe '+blendshapeNode+'.inputTarget[0].inputTargetGroup[1].targetWeights['+str(i)+']')
            
        else:
            
            cmds.setAttr(blendshapeNode+'.inputTarget[0].inputTargetGroup[1].targetWeights['+str(i)+']',0.0)
            
            mel.eval('setKeyframe '+blendshapeNode+'.inputTarget[0].inputTargetGroup[1].targetWeights['+str(i)+']')
            
        # Y setBlendShapes key everyFrame
        
        if distance[frameRange][i][1] > 0:
            
            cmds.setAttr(blendshapeNode+'.inputTarget[0].inputTargetGroup[2].targetWeights['+str(i)+']',distance[frameRange][i][1])
            
            mel.eval('setKeyframe '+blendshapeNode+'.inputTarget[0].inputTargetGroup[2].targetWeights['+str(i)+']')
            
        else:
            
            cmds.setAttr(blendshapeNode+'.inputTarget[0].inputTargetGroup[2].targetWeights['+str(i)+']',0.0)
            
            mel.eval('setKeyframe '+blendshapeNode+'.inputTarget[0].inputTargetGroup[2].targetWeights['+str(i)+']')
            
        
        if distance[frameRange][i][1] < 0:
            
            cmds.setAttr(blendshapeNode+'.inputTarget[0].inputTargetGroup[3].targetWeights['+str(i)+']',(-1*distance[frameRange][i][1]))
            
            mel.eval('setKeyframe '+blendshapeNode+'.inputTarget[0].inputTargetGroup[3].targetWeights['+str(i)+']')
            
        else:
            
            cmds.setAttr(blendshapeNode+'.inputTarget[0].inputTargetGroup[3].targetWeights['+str(i)+']',0.0)
            
            mel.eval('setKeyframe '+blendshapeNode+'.inputTarget[0].inputTargetGroup[3].targetWeights['+str(i)+']')


        # Z setBlendShapes key everyFrame
        
        if distance[frameRange][i][2] > 0:
            
            cmds.setAttr(blendshapeNode+'.inputTarget[0].inputTargetGroup[4].targetWeights['+str(i)+']',distance[frameRange][i][2])
            
            mel.eval('setKeyframe '+blendshapeNode+'.inputTarget[0].inputTargetGroup[4].targetWeights['+str(i)+']')
            
        else:
            
            cmds.setAttr(blendshapeNode+'.inputTarget[0].inputTargetGroup[4].targetWeights['+str(i)+']',0.0)
            
            mel.eval('setKeyframe '+blendshapeNode+'.inputTarget[0].inputTargetGroup[4].targetWeights['+str(i)+']')
            
        
        if distance[frameRange][i][2] < 0:
            
            cmds.setAttr(blendshapeNode+'.inputTarget[0].inputTargetGroup[5].targetWeights['+str(i)+']',(-1*distance[frameRange][i][2]))
            
            mel.eval('setKeyframe '+blendshapeNode+'.inputTarget[0].inputTargetGroup[5].targetWeights['+str(i)+']')
            
        else:
            
            cmds.setAttr(blendshapeNode+'.inputTarget[0].inputTargetGroup[5].targetWeights['+str(i)+']',0.0)
            
            mel.eval('setKeyframe '+blendshapeNode+'.inputTarget[0].inputTargetGroup[5].targetWeights['+str(i)+']')
    
    settime = cmds.currentTime( time+1, edit=True )
    frameRange=frameRange+1

 

I have just use simple equation (distance / frames)/(frames per second) to calculate it and gotten very promising results. The problem I have run into is when it comes to calculating which direction to morph the sphere in. If the sphere is theoretically moving in an +X direction in world space, and the object was not rotated in local space at all, I would simply apply the intensity to the -X morph to create drag.

 

However, if I rotate the object at all in local space, for example in 90° in X, the morph is now facing the wrong direction, the morph will be facing +Z, when I need it to the towards the -X world axis. In summary, I need to come up with a way to recalculate which local axis direction (or directions) closest match the world axis directions, so I can maintain the drag on the sphere, despite local space rotation.

 

If anyone can give me some help trying to figure out the math for getting this to work, that would be beyond helpful!

 

Thanks guys!

 

Joe.

 

0 Likes
431 Views
0 Replies
Replies (0)