expressing face normals as euler rotation

1,848 views
Skip to first unread message

pric...@googlemail.com

unread,
Feb 24, 2009, 10:41:28 PM2/24/09
to python_inside_maya
suppose i have a face normal info vector array? and i want this to be
expressed as a euler rotation ? any clues ? ? ? essentially i need a
torus to be in parallel to another face ? am i being a moron ? i m
sure i am and i bet there is a very simple method but i m just messing
around with a script i found but it does nt seem to be in the right
ball park. This is MEL but i ve written the python wrapper ....


vector $up = <<0.5 , 0.5 , 0.5>>;
vector $direction = <<$x, $y , $z >> ;


// calculate the side vector
vector $sideVec = cross( $up, $direction );
vector $upVec = cross( $direction, $sideVec );

float $cosY = sqrt( ($sideVec.x)*($sideVec.x) + ($sideVec.y)*
($sideVec.y) );

// solve each angle
float $rotZ = atan2( ($sideVec.y), ($sideVec.x) );
float $rotY = atan2( -($sideVec.z), ( (($sideVec.x)+
($sideVec.y)) / (cos( $rotZ ) + sin( $rotZ ) ) ) );
float $rotX = atan2( ($upVec.z), ($direction.z) );

// convert to degrees
$rotX = rad_to_deg( $rotX );
$rotY = rad_to_deg( $rotY );
$rotZ = rad_to_deg( $rotZ );

// return x,y,z rotations
print $rotX; print " ";
print $rotY; print " ";
print $rotZ;


i m pretty sure i m not giving it the right inputs but what does it
want !?!?! Any help would be greatly appreciated ?

ugly bob

unread,
Feb 24, 2009, 11:59:03 PM2/24/09
to python_inside_maya
YEY, you can all ignore that and i am quite smug to say i solved it !!
using the API goodness. i' m getting the hang of this. slightly
annoying there s no python command to change rad_to_deg as my method
outputs radians but thats no biggy. This code will take face normal
data (or any other normal data for that matter) as an om.MVector and
return an om.MEulerRotation value, which can be queried as x y z. Go
me !


torusNormal = om.MVector(0,1,0)
chips=om.MQuaternion()
chips=torusNormal.rotateTo(vector)
red=chips.asEulerRotation()
print red.x
print red.y
print red.z

by setting torusnormal to (0,1,0) it is essentially the directional
value it has when its created. after doing it i realise how simple
this actually was....

ugly bob

unread,
Feb 25, 2009, 12:01:36 AM2/25/09
to python_inside_maya
does any one else think its kinda funny you have to call it as a
quaternion, then convert to euler? I looked to do it straight from
Mvector to MEulerRotation but it appeared to not exist ?

ryant

unread,
Feb 25, 2009, 2:34:21 AM2/25/09
to python_inside_maya
MQuaternion is a good way to get the MEulerRotation. At least its the
only way I have used. There is actually a bug in the Maya API that
does not even let you get the rotation from the MTransformationMatrix
class.

This will error:

import maya.OpenMaya as OpenMaya

getMatrix = OpenMaya.MMatrix()
matrixList = ( 0.673, 1.545 , 0.0, 0.0,
-0.327, 2.545, 0.0, 0.0,
-0.327, 1.545, 1.0, 0.0,
-0.327, 1.545, 0.0, 1.0)

OpenMaya.MScriptUtil().createMatrixFromList(matrixList, getMatrix)

mTM = OpenMaya.MTransformationMatrix( getMatrix )

rotDoubleArray = OpenMaya.MScriptUtil()
rotDoubleArray.createFromList( [0.0, 0.0, 0.0], 3 )
rotDoubleArrayPtr = rotDoubleArray.asDoublePtr()
rotOrder = OpenMaya.MTransformationMatrix().kXYZ

mTM.getRotation( rotDoubleArrayPtr, rotOrder )

# Error: Wrong number of arguments for overloaded function
'MTransformationMatrix_getRotation'.
Possible C/C++ prototypes are:
getRotation(double [3],MTransformationMatrix::RotationOrder &)
getRotation(double [3],MTransformationMatrix::RotationOrder
&,MSpace::Space)
# Traceback (most recent call last):
# File "", line 1, in
# File "C:\buildforge\Maya_Main_Win32_Build\build\wrk\optim\runTime
\Python\Lib\site-packages\maya\OpenMaya.py", line 8044, in getRotation
# NotImplementedError: Wrong number of arguments for overloaded
function 'MTransformationMatrix_getRotation'.
# Possible C/C++ prototypes are:
# getRotation(double [3],MTransformationMatrix::RotationOrder &)
# getRotation(double [3],MTransformationMatrix::RotationOrder
&,MSpace::Space)
# #

The only way around it is with MQuaternion() example here:

import maya.OpenMaya as OpenMaya

getMatrix = OpenMaya.MMatrix()
matrixList = ( 0.673, 1.545 , 0.0, 0.0,
-0.327, 2.545, 0.0, 0.0,
-0.327, 1.545, 1.0, 0.0,
-0.327, 1.545, 0.0, 1.0)

OpenMaya.MScriptUtil().createMatrixFromList(matrixList, getMatrix)

mTM = OpenMaya.MTransformationMatrix( getMatrix )
rotOrder = OpenMaya.MTransformationMatrix().kXYZ

# Get the rotation as a quaternion then convert to Euler as needed
rotateOrder = 0
mquat = mTM.rotation()
rot = mquat.asEulerRotation()
rot.reorderIt( rotateOrder )

print rot.x, rot.y, rot.z

RyanT
Technical Artist
www.rtrowbridge.com/blog
Naughty Dog Inc.

Judd Simantov

unread,
Feb 25, 2009, 5:47:09 AM2/25/09
to python_in...@googlegroups.com
You can also just get your euler rotations directly without having to first get a quaternion...

In Ryan's code you would just do this:

vec = mTM.eulerRotation().asVector()

if you wanted it as a vector obviously...

ugly bob

unread,
Feb 25, 2009, 8:55:34 AM2/25/09
to python_inside_maya

interesting. in the interest of ease of use i m gonna stick with the
quaternion work around. interesting bug. i m trying to get the euler
rotations, from a translate vector i think? that is to transform a
torus to the rotation of a face, via queried facenormal values. its
all good now though. spent ages wrapping that mel script but the API
goodness comes through again! hurrah !

Matthew Chapman

unread,
Feb 25, 2009, 12:10:57 PM2/25/09
to python_in...@googlegroups.com
I think it would be more accurate to use one of the methods that pulls the Euler rotation from a matrix like Ryan and Judd suggested.

import math
import maya.OpenMaya as mApi

def getOrient(normal, tangent, ro=0):
    kRotateOrders = [mApi.MEulerRotation.kXYZ, mApi.MEulerRotation.kYZX,
                     mApi.MEulerRotation.kZXY, mApi.MEulerRotation.kXZY,
                     mApi.MEulerRotation.kYXZ, mApi.MEulerRotation.kZYX,]
    cross = [normal[1]*tangent[2] - normal[2]*tangent[1],
         normal[2]*tangent[0] - normal[0]*tangent[2],
         normal[0]*tangent[1] - normal[1]*tangent[0]]
    tMatrix  = normal+[0]+tangent+[0]+cross+[0,0,0,0,1]
    mMatrix  = mApi.MMatrix()
    mApi.MScriptUtil.createMatrixFromList(tMatrix, mMatrix)
    tmMatrix = mApi.MTransformationMatrix(mMatrix)
    rotate   = tmMatrix.eulerRotation().reorder(kRotateOrders[ro])
    RAD_to_DEG    = (180/math.pi)
    return [rotate[0]*RAD_to_DEG,  rotate[1]*RAD_to_DEG,  rotate[2]*RAD_to_DEG]
getOrient([1,0,0], [0,1,0], ro=0)
Reply all
Reply to author
Forward
0 new messages