Load a character

Load a skinned mesh using USD and animate it

[1]:
import numpy as np
from ipywidgets import widgets, interact, interactive

import ipyanimlab as lab
viewer = lab.Viewer(shadow_quality=lab.ShadowQuality.HIGH, move_speed=5, width=800, height=600)

Load the USD Asset

the default skinned character is accessible directly from internal resources

[2]:
character = viewer.import_usd_asset('AnimLabSimpleMale.usd')
[3]:
character.bone_names()
[3]:
['Root',
 'Hips',
 'Spine',
 'Spine1',
 'Spine2',
 'Neck',
 'Head',
 'LeftShoulder',
 'LeftArm',
 'LeftForeArm',
 'LeftHand',
 'RightShoulder',
 'RightArm',
 'RightForeArm',
 'RightHand',
 'LeftUpLeg',
 'LeftLeg',
 'LeftFoot',
 'LeftToe',
 'RightUpLeg',
 'RightLeg',
 'RightFoot',
 'RightToe']

Render the character in tpose

by calling the draw command without any matrices, we will render it with the default bindpose

[4]:
viewer.begin_shadow()
# draw the character with bindpose
viewer.draw(character)
viewer.end_shadow()

viewer.begin_display()
# draw the default ground
viewer.draw_ground()
# draw the character with bindpose
viewer.draw(character)
viewer.end_display()

# disable DEPTH_TEST so we can draw on top of the scene
viewer.disable(depth_test=True)

# draw XYZ axis for each bone of the character
viewer.draw_axis(character.world_skeleton_xforms(), 5)
# draw black lines between each joints
viewer.draw_lines(character.world_skeleton_lines())

viewer.execute_commands()
viewer
[4]:

Render and update some bones

[5]:
xforms = np.eye(4, dtype=np.float32)[np.newaxis, ...].repeat(2, axis=0)
xforms[0, :3, 3] = [10, -10, 20]
xforms[1, :3, 3] = [10, -10, -20]

viewer.begin_shadow()
# passing a few matrices to the draw command, with the names of the bones for which we have given the matrices
viewer.draw(character, xforms, ['LeftArm', 'RightArm'])
viewer.end_shadow()

viewer.begin_display()
viewer.draw_ground()
# passing a few matrices to the draw command, with the names of the bones for which we have given the matrices
viewer.draw(character, xforms, ['LeftArm', 'RightArm'])
viewer.end_display()

viewer.disable(depth_test=True)

# passing a few matrices to the draw command, with the names of the bones for which we have given the matrices
viewer.draw_axis(character.world_skeleton_xforms(xforms, ['LeftArm', 'RightArm']), 5)
# passing a few matrices to the draw command, with the names of the bones for which we have given the matrices
viewer.draw_lines(character.world_skeleton_lines(xforms, ['LeftArm', 'RightArm']))

viewer.execute_commands()
viewer
[5]:

Load an animation.

We will load an animation saved as usd stage.

[8]:
anim = lab.import_usd_animation('example_animation.usd')
[10]:
def render(frame):

    p = (anim.pos[frame,...])
    q = (anim.quats[frame,...])

    a = lab.utils.quat_to_mat(q, p)
    viewer.set_shadow_poi(p[0])

    viewer.begin_shadow()
    # render giving the computed pose this frame, and the bones names from the animation
    viewer.draw(character, a, anim.bones)
    viewer.end_shadow()

    viewer.begin_display()
    viewer.draw_ground()
    # render giving the computed pose this frame, and the bones names from the animation
    viewer.draw(character, a, anim.bones)
    viewer.end_display()

    viewer.disable(depth_test=True)

    # render giving the computed pose this frame, and the bones names from the animation
    viewer.draw_axis(character.world_skeleton_xforms(a, anim.bones), 5)
    # render giving the computed pose this frame, and the bones names from the animation
    viewer.draw_lines(character.world_skeleton_lines(a, anim.bones))

    viewer.execute_commands()

interact(
    render,
    frame=lab.Timeline(max=anim.quats.shape[0]-1)
)
viewer
[10]: