I’m not entirely sure what it is you are trying to do.
This is how I’m interpreting it:
- From an object you’re looking to get the average face normal
- Then align the pivot (Y-axis) with this average face normal.
Let’s first get the average face normal. I’m more fluent in Python so I’ll do that. However, I’ll write it without using API functions so it translates somewhat well to MEL.
from maya import cmds
def get_average_face_normal(node):
"""Return average face normal of geometry in object-space.
Note that the function might return [0, 0, 0]
for e.g. a cube since all normals point in
exactly opposite directions.
Args:
node (str): Node name of mesh.
Returns:
list: vector of average normal
"""
data = cmds.polyInfo(node, faceNormals=True)
normals = []
for entry in data:
# entry = 'FACE_NORMAL 0: 0.000000 0.000000 1.000000\n'
values = entry.split(": ")[-1].strip()
# values = 0.000000 0.000000 1.000000
normal = [float(x) for x in values.split(" ")]
# normal = [0.0, 0.0, 1.0]
normals.append(normal)
# To get the average normal we'll just sum all elements
# and then divide by the amount of normals
result = [0, 0, 0]
for normal in normals:
for i in range(3):
result[i] += normal[i]
for i in range(3):
result[i] /= float(len(normals))
return result
for node in cmds.ls(sl=1):
average = get_average_face_normal(node)
Then now let’s try and align the pivot with that average normal. This is where I’m not sure what you’re trying to do. Are you trying to rotate the geometry in such a way that the average normal points to the Y-axis. Or are you trying to set a transform tool to a Custom pivot. I don’t believe objects actually have ‘rotation’ for a pivot in maya.
Anyway, here’s an example using Maya’s Python API to use some vector/matrix math from it:
from maya import cmds
import maya.api.OpenMaya as om
import math
for node in cmds.ls(sl=1):
average = get_average_face_normal(node)
normal = om.MVector(*average)
if normal.length() == 0:
raise RuntimeError("Average normal is of zero length, rotation can't be defined.")
# Make the average world-space
xform = cmds.xform(node, query=True, worldSpace=True, matrix=True)
matrix = om.MMatrix(xform)
normal *= matrix
# Rotate to have the normal aim to Y-axis
rotation = normal.rotateTo(om.MVector.kYaxisVector) # maya.api.OpenMaya.MQuaternion
euler = rotation.asEulerRotation().asVector() # maya.api.OpenMaya.MVector
# Euler angles are in radians, we need to convert to degrees
euler = [x * (180/math.pi) for x in euler]
cmds.xform(node, relative=True, worldSpace=True, rotation=list(euler))
This second snippet uses the code/function from the first snippet.
This will rotate the geometry so that the average normal matches the Y-axis. Note that it won’t work for a cube due to the average normal being zero length [0, 0, 0].