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

- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report
So, in Maya , you have an object. In this case a Sphere
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.
In Maya you can access the following information about any object:
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
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.