It's been a long time since I dealt with quaternions at this level, but if I understand your question correctly, yeah Maya will reverse the quaternion once you pass 180. Actually it's not Maya doing that. A quaternion can distinguish between, say, +270 and -90, but a transform matrix can only encode the resulting angle, so it can't tell the difference between the two. If you want to keep that distinction, you need to stay in quaternions and not use matrices (or Euler angles) at all.
Are you getting better results using your own quaternion_from_matrix code? If so, then I've misunderstood something... By the way, your slerp function appears to be missing something. Near the end, you lerp, but you don't use your f_scale numbers. Should be scaling by them somewhere? As it is, you're just lerping. If you can be a bit more specific about what works and what doesn't, I'd be happy to try to help more. On Friday, 15 September 2017 23:35:08 UTC+10, Rémi Deletrain wrote: > > Hello everyone, > > I try to make a slerp between two quaternions. > I have a formula that works, but I encounter a problem with maya ... > > This is my slerp function: > > def slerp_quaternion(m_quaternion_1, m_quaternion_2, f_weight): > > m_quaternion_1 = m_quaternion_1.normal() > m_quaternion_2 = m_quaternion_2.normal() > > # If is equial return first quaternion > if m_quaternion_1.isEquivalent(m_quaternion_2): > return m_quaternion_1 > > # If the dot product is negative, the quaternions > # have opposite handed-ness and slerp won't take > # the shorter path. Fix by reversing one quaternion. > # dot = dot_product(m_quaternion_1, m_quaternion_2) > dot = dot_product(m_quaternion_1, m_quaternion_2) > if dot < 0.0: > m_quaternion_2.negateIt() > dot *= -1.0 > > # Weight Blend > f_scale_1 = 1.0 - f_weight > f_scale_2 = f_weight > > # Get Quaternion median > dot = max(min(dot, 1.0), -1.0) > f_theta = math.acos(dot) > f_sin_theta = math.sin(f_theta) > > f_scale_1 = math.sin(f_scale_1 * f_theta) / f_sin_theta > f_scale_2 = math.sin(f_scale_2 * f_theta) / f_sin_theta > > # New Quaternion > a_new_values = [] > for i in xrange(4): > a_new_values.append(lerp(m_quaternion_1[i], m_quaternion_2[i], > f_weight)) > > return pmc.datatypes.Quaternion(a_new_values[0], a_new_values[1], > a_new_values[2], a_new_values[3]) > > > > In Maya, if I take two quaternions from an MFnTransform (getRotation) and > I turn a transform on an axis I have: > - A dot > 0 between 0 ° and 180 ° > - A dot < 0 if I am between 180 * and 270 *. > > If I do this in a custom node since a matrix my dowry is always positive > no matter what happens ... > In Maya to get quaternion from a matrix you have to go through the > MTransformationMatrix. And that only changes the value of my quaternions > once I pass the 180 °. > Maya automatically reverse quaternion ? If is that, how i made a gool > slerp ? ... > So, I also have a function to getter the quaternion since any matrix: > > def quaternion_from_matrix(m_matrix): > > w = math.sqrt(max(0, 1 + m_matrix(0, 0) + m_matrix(1, 1) + m_matrix(2, > 2))) / 2.0 > x = math.sqrt(max(0, 1 + m_matrix(0, 0) - m_matrix(1, 1) - m_matrix(2, > 2))) / 2.0 > y = math.sqrt(max(0, 1 - m_matrix(0, 0) + m_matrix(1, 1) - m_matrix(2, > 2))) / 2.0 > z = math.sqrt(max(0, 1 - m_matrix(0, 0) - m_matrix(1, 1) + m_matrix(2, > 2))) / 2.0 > > x *= -1 if x * (m_matrix(2, 1) - m_matrix(1, 2)) >= 0.0 else 1 > y *= -1 if y * (m_matrix(0, 2) - m_matrix(2, 0)) >= 0.0 else 1 > z *= -1 if z * (m_matrix(1, 0) - m_matrix(0, 1)) >= 0.0 else 1 > > return OpenMaya.MQuaternion(x, y, z, w) > > > > -- You received this message because you are subscribed to the Google Groups "Python Programming for Autodesk Maya" group. To unsubscribe from this group and stop receiving emails from it, send an email to [email protected]. To view this discussion on the web visit https://groups.google.com/d/msgid/python_inside_maya/a5e5b053-3ef3-47fc-9b57-bb0521c3260f%40googlegroups.com. For more options, visit https://groups.google.com/d/optout.
