[QUOTE=Theodox;27049]Inside maya, this is actually a UI issue: the manipulations are done in matrices but then converted to eulers. Unfortunately the conversion between matrices and euler rotations is not deterministic (hence, all the damn Euler flip issues that plague maya animations). It’s based on conventions – that’s why we specify rotation order in Maya transforms – but even then a 0,0,0 rotation and a 0,0,720 rotation create the exact same matrix. So you can’t rely on the numbers that come out of constraints or IKs to behave the way you expect in Euler space.

Quaternions suffer from a related problem. Like matrices, they don’t represent actions: they represent orientations. Thus there is no quaternion equivalent of ‘900 degrees’.

You could achieve the visual result by iteratively applying your quaternion rotation to the same object, however: 10 90 degree relative rotations will be the same as a single 900 degree rotation.

The other complication is that not all matrix > euler or euler > matrix conversions are equal: in particular, if you send Maya data to another program your maya rotation order and the other programs euler conversion rotation order are different you’ll get visually similar results. If you’re sending the data yourself, matrices or quaternions are better than eulers because they don’t rely on other knowledge.[/QUOTE]

The game uses Quaternions for rotations, when I took the euler values and converted to quaternions to put in the game, -90 degree to 180 degrees displays fine, it’s after 180 degrees that it switched x:180 y:0 to x:0 y:180, and reset z to 0 which increments to 90…So it’s effectively the same as as the first quarter of the circle/ring. If I manually fix the euler values it’ll convert fine, it’s just maya’s duplicate transforms that did this odd behaviour. Perhaps I didn’t convert euler to quaternion right? seems fine for everything else though.

def crop_rotation(angle):

if angle > 180:

return angle-360

elif angle < -180:

return angle+360

else:

return angle

def convert_to_radians(degrees):

return (degrees/180) * math.pi

def euler_to_quaternion(angle_x, angle_y, angle_z):

heading = convert_to_radians(angle_y)

attitude = convert_to_radians(angle_z)

bank = convert_to_radians(angle_x)

```
c1 = math.cos(heading/2)
c2 = math.cos(attitude/2)
c3 = math.cos(bank/2)
```

```
s1 = math.sin(heading/2)
s2 = math.sin(attitude/2)
s3 = math.sin(bank/2)
```

```
w = (c1 * c2 * c3) - (s1 * s2 * s3)
x = (s1 * s2 * c3) + (c1 * c2 * s3)
y = (s1 * c2 * c3) + (c1 * s2 * s3)
z = (c1 * s2 * c3) - (s1 * c2 * s3)
```

```
return Quaternion(w, x, y, z)
```

# snippet of relevant code using the above functions

# angles x/y are flipped to match the game engines correctly

# angles are cropped to fit into -180 to 180 bounds, may not be necessary?

angleX = crop_rotation(cm.getAttr(selected+‘.rx’)*-1)*

angleY = crop_rotation(cm.getAttr(selected+‘.ry’)-1)

angleZ = crop_rotation(cm.getAttr(selected+‘.rz’))

q = euler_to_quaternion(angleX, angleY, angleZ)

I tried @rgkovach123’s solution, locking x/y rotations and then shift+d after the first duplicate rotation to test this out, this was the result:

If I keep x/y at 0 degrees instead of one being 180 though, regardless if I lock the axis, everything is fine: