Although I have read some stuff about the armature system being majorly redone, for now and if the problem persists is a solution to obtaining World-Oriented Quaternions. I have tried to test this a lot, and I think that it works, but if you find some situation in which it does not work, please tell me. I will try to fix it, as I must also use this :).
Oh, and I think that there’s something about not creating armatures except in the XY view… not doing this seems to mess up the rotations.
Auxiliary Quaternion Code:
def QuatMultiply(Quat1, Quat2): Cv = Blender.Mathutils.Vector([Quat1.x, Quat1.y, Quat1.z]) Cw = Quat1.w v = Blender.Mathutils.Vector([Quat2.x,Quat2.y,Quat2.z]) w = Quat2.w Nv = Blender.Mathutils.CrossVecs(Cv, v) + w * Cv + Cw * v Nw = Cw * w - Blender.Mathutils.DotVecs(Cv, v) return Blender.Mathutils.Quaternion([Nw, Nv.x, Nv.y, Nv.z]) def QuatConverse(Quat): # Note that the converse is equal to the inverse if the quaternion is normalized Quat.conjugate() return Quat
- QuatMultiply is used exclusively for concatenating rotations exclusively. I could find no blender tools for doing this. The conjugate one I made before I found Quat.conjugate(), but it allows for shortening of the code.
Now for the goodies:
def GetRootQuat(QuatBone): # Get parents' roots # Then calculate root rotation based on head, tail, and roll # append to root rotation RootQuat = Blender.Mathutils.Quaternion([1, 0, 0, 0]) if QuatBone.hasParent() == 1: RootQuat = QuatMultiply(RootQuat, GetRootQuat(QuatBone.getParent())) RootQuat.normalize() Vect = (QuatBone.getTail() - QuatBone.getHead()) Vect.normalize() Target = Blender.Mathutils.Vector([0, 1, 0]) if Blender.Mathutils.DotVecs(Target, Vect) > 0.99999999: return RootQuat VectCross = Blender.Mathutils.CrossVecs(Target, Vect) ThisRootQuat = Blender.Mathutils.Quaternion([VectCross.x, VectCross.y, VectCross.z], Blender.Mathutils.AngleBetweenVecs(Target, Vect)) RootQuat = QuatMultiply(ThisRootQuat, RootQuat) RootQuat = QuatMultiply(Blender.Mathutils.Quaternion([0, 1, 0], QuatBone.getRoll()), RootQuat) RootQuat.normalize() return RootQuat def GetFixedQuat(QuatBone): # Rotation order: """ Remember: Multiplying quaternions concatenates them -- you cannot transorm a quaternion, only an object. Therefore one must concatenate them in the right order to simulate this transormation. 1. Rotate object by reverse root 2. Rotate object by its own quaternion 3. Rotate object back by root 4. Apply parents' rotations (from bottom up). This function is called recursively to do so. 1-3: The root quaternion (GetRootQuat) is the rotation that if applied to the anim-quat would make it aligned to its parent. However, because of the lack of quaternion-quaternion transformations (AFAIK), the solution must be done with concatenations only. 4: Self explanatory... just apply all the other fixed rotations afterwords in order, down the parent->child chain. """ QuatRoot = QuatConverse(GetRootQuat(QuatBone)) QuatRoot = QuatMultiply(QuatBone.getQuat(), QuatRoot) QuatRoot = QuatMultiply(GetRootQuat(QuatBone), QuatRoot) if QuatBone.hasParent() == 1: QuatRoot = QuatMultiply(GetFixedQuat(QuatBone.getParent()), QuatRoot) QuatRoot.normalize() return QuatRoot
As most of you probably already know, or don’t, Blender stores its rotations as relative to a root rotation. The root rotation calculates the rotation that if applied to the other rotations, would orient them for the object. However, as far as I can tell the only way to achieve this is by concatenating the rotations. Solution: Rotate the object backwards by the root (conjugate of root), apply rotations, and then rotate back.
Once again, please tell me if this is at all useful and working. Thanks!