Search code examples
algorithmanimation3drotationmotionbuilder

How to calculate rotation just like in MotionBuilder


Problem:

My goal is to write a code, that rotates the root joint of a bvh, θ degrees around global y axis3, and keeps values in the range of -180 to 180 (just like MotionBuilder does). I have tried to rotate a joint using euler, quaternions, matrices (considering the rotational order of a bvh) but I haven't yet figured out how to get the correct values. MotionBuilder calculates the values x,y,z so they are valid for the bvh file. I would like to write a code that calculates the rotation x,y,z for a joint, just like in MotionBuilder.

Example:

Initial: Root rotation: [x= -169.56, y=15.97, z=39.57]

Initial rotations of root joint (in motionbuilder)

After manually rotating about 45 degrees: Root rotation: [x=-117.81, y=49.37, z=70.15]

rotations of root joint after rotating around y global axis

global y axis:

global axes


Solution

  • To rotate a node around the world Y axis any number of degrees the following works (https://en.wikipedia.org/wiki/Rotation_matrix):

    import math
    from pyfbsdk import *
    
    angle = 45.0
    radians = math.radians(angle)
    root_matrix = FBMatrix()
    root.GetMatrix(root_matrix, FBModelTransformationType.kModelRotation, True)
    
    transformation_matrix = FBMatrix([
        math.cos(radians), 0.0, math.sin(radians), 0.0,
        0.0, 1.0, 0.0, 0.0,
        -math.sin(radians), 0.0, math.cos(radians), 0.0,
        0.0, 0.0, 0.0, 1.0
    ])
    
    result_matrix = root_matrix * transformation_matrix
    root.SetMatrix(result_matrix , FBModelTransformationType.kModelRotation, True)
    

    If there are any Pre-Rotations on the root node the process is more complex and you can try setting the Rotations using the SetVector with the LRMToDof method.

    result_vector = FBVector3d()
    root.LRMToDof(result_vector, result_matrix)
    root.SetVector(result_vector, FBModelTransformationType.kModelRotation, True)