Skip to article frontmatterSkip to article content

Chapter 7

7.1.2 Setting the Stage’s Metadata

Create a new stage with .usda format

from pxr import Usd, UsdGeom, Gf, Sdf
stage = Usd.Stage.CreateNew("animation.usda")

Set time

fps = 30.0
stage.SetTimeCodesPerSecond(fps)    
stage.SetStartTimeCode(0)   
stage.SetEndTimeCode(59)    
stage.Save()

7.2.2 Animating Xforms

Listing 6.1 Create a Cube and Add Keyframe Animation To It

cube  = UsdGeom.Cube.Define(stage, "/World/Cube")    

transform_op = cube.AddTranslateOp(precision=UsdGeom.XformOp.PrecisionDouble)    
transform_op.Set(value=Gf.Vec3d(0, 0, 0), time=Usd.TimeCode(0))    
transform_op.Set(Gf.Vec3d(10, 0, 0), Usd.TimeCode(30))    

stage.Save()

Keyframing rotation: setting the cube’s initial rotation at frame 0 and rotating the cube 90 degrees around the Z-axis by frame 30:

rotation_op = cube.AddRotateXYZOp(precision=UsdGeom.XformOp.PrecisionDouble)    
rotation_op.Set(Gf.Vec3d(0,0,0),0)    
rotation_op.Set(Gf.Vec3d(0,0,90),30)    
stage.Save()

Use quaternion to represent the rotation:

import math   
UsdGeom.Xformable(cube).ClearXformOpOrder()    
cube.AddTranslateOp()    
rotation_op = cube.AddOrientOp(precision=UsdGeom.XformOp.PrecisionDouble)    
rotation_op.Set(Gf.Quatd(1,0,0,0),0)    
rotation_op.Set(Gf.Quatd(math.sqrt(2)/2,0,0,math.sqrt(2)/2),30)    
stage.Save()

Add scale animation

scale_op = cube.AddScaleOp(precision=UsdGeom.XformOp.PrecisionDouble)    
scale_op.Set(Gf.Vec3d(1,1,1), 0)    
scale_op.Set(Gf.Vec3d(5,5,5), 30)    
stage.Save()

7.2.3 Influencing Interpolation

Move the first cube away

transform_op.Set(Gf.Vec3d(0, 0, -20),0)    
transform_op.Set(Gf.Vec3d(10, 0, -20),30)    

Create a second cube and add a translate_op

cube2 = UsdGeom.Cube.Define(stage, "/World/Cube2")    
translate_op = cube2.AddTranslateOp(precision=UsdGeom.XformOp.PrecisionDouble)    

Set up the keyframe values

P0 = Gf.Vec3d(0, 0, 0)    
P1 = Gf.Vec3d(10, 0, 0)    
M0 = Gf.Vec3d(0.05, 0, 0)    
M1 = Gf.Vec3d(-0.05, 0, 0)    

Listing 6.2 Define the Helper Function for Cubic Hermite Interpolation.

def cubic_hermite(P0, P1, M0, M1, t):
	"""
	Perform cubic Hermite interpolation.
    
	Parameters:
	P0, P1: float or np.array
    		The start and end keyframe values.
	M0, M1: float or np.array
    		The tangents at the start and end keyframes.
	t: float
    		The normalized time between P0 and P1 (0 <= t <= 1).
    
	Returns:
	float or np.array
    	The interpolated value.
	"""
	h00 = 2 * t**3 - 3 * t**2 + 1
	h10 = t**3 - 2 * t**2 + t
	h01 = -2 * t**3 + 3 * t**2
	h11 = t**3 - t**2
    
	return h00 * P0 + h10 * M0 + h01 * P1 + h11 * M1

Loop through the frame to get the cubic Hermite interpolation

for frame in range(0, 31):    
	t = frame / 30.0    
	interpolated_value = cubic_hermite(P0, P1, M0, M1, t)    
	translate_op.Set(interpolated_value, Usd.TimeCode(frame))    

Similar approach applied to rotaion Euler angles:

rotation_op = cube2.AddRotateXYZOp(precision=UsdGeom.XformOp.PrecisionDouble)

R0 = Gf.Vec3d(0, 0, 0)   	
R1 = Gf.Vec3d(0, 0, 90)  	
T0_rot = Gf.Vec3d(0, 0, 1)  
T1_rot = Gf.Vec3d(0, 0, -1) 
for frame in range(0, 31):  
	t = frame / 30.0   
	interpolated_rotation = cubic_hermite(R0, R1, T0_rot, T1_rot, t)
	rotation_op.Set(interpolated_rotation, Usd.TimeCode(frame))

Similar approach applied to scale

scale_op = cube2.AddScaleOp(precision=UsdGeom.XformOp.PrecisionDouble)
S0 = Gf.Vec3d(1, 1, 1)	
S1 = Gf.Vec3d(5, 5, 5)	
T0_scale = Gf.Vec3d(0.1, 0.1, 0.1)  
T1_scale = Gf.Vec3d(-0.1, -0.1, -0.1)
for frame in range(0, 31):    
	t = frame / 30.0    
	interpolated_scale = cubic_hermite(S0, S1, T0_scale, T1_scale, t)
	scale_op.Set(interpolated_scale, Usd.TimeCode(frame))

stage.Save()

7.2.4 Animating Attributes

Get the translate attribute and edit

cube_prim = stage.GetPrimAtPath('/World/Cube')    
cube_prim.GetAttribute("xformOp:translate").Set(Gf.Vec3d(0,0,-20), 0)    
cube_prim.GetAttribute("xformOp:translate").Set(Gf.Vec3d(0,10,-20), 30)    
stage.Save()

Creates a Rect Light, then positions, resizes and sets its intensity

from pxr import UsdLux

light = UsdLux.RectLight.Define(stage, "/World/Lights/Light")    

light.AddTranslateOp().Set(Gf.Vec3d(25, 25, -10))
light.AddRotateXYZOp().Set(Gf.Vec3d(-90, 0, -45))
light.GetHeightAttr().Set(60)
light.GetWidthAttr().Set(30)    

light.GetIntensityAttr().Set(30000)    

stage.Save()

Animate the light’s intensity gradually

intensity_attr = light.GetIntensityAttr()    

intensity_attr.Set(0, 0)     
intensity_attr.Set(30000, 30) 
intensity_attr.Set(0, 59)    

Change light color

color_attr = light.GetColorAttr()    

color_attr.Set(Gf.Vec3f(1, 0, 0), 0)    
color_attr.Set(Gf.Vec3f(1, 1, 1), 30)    
color_attr.Set(Gf.Vec3f(1, 0, 0), 59)    

stage.Save()

Schema specific attributes can be cleared

light.GetIntensityAttr().ClearAtTime(0)

or

light.GetIntensityAttr().Clear()

Clear the light intensity keyframe at 0 and 59

light.GetIntensityAttr().ClearAtTime(0)    
light.GetIntensityAttr().ClearAtTime(59)    

Add a camera to the stage that is facing two cubes

camera = UsdGeom.Camera.Define(stage, "/World/Camera")

translate_op = camera.AddTranslateOp()
translate_op.Set(Gf.Vec3d(30, 30, 100))
rotate_op = camera.AddRotateXYZOp()
rotate_op.Set(Gf.Vec3d(-12, 12, 0))

stage.Save()

Create a zoom effect on the camera

camera.GetFocalLengthAttr().Set(30, (0))    
camera.GetFocalLengthAttr().Set(100, (50))    

stage.Save()

7.3 Combining Animations in One Clip

Set working directory

import os    
new_directory = <'/your/path/to/Ch06 ex:'D://Ch06''>    
os.chdir(new_directory)    

Create a new stage ‘fan_animation’ and set the stage’s properties with six-second animation at 24 fps

from pxr import Usd, UsdGeom, Sdf, Gf, UsdLux
stage = Usd.Stage.CreateNew("fan_animation.usda")

fps = 24.0
stage.SetTimeCodesPerSecond(fps)
stage.SetStartTimeCode(0)
stage.SetEndTimeCode(143)

Import the fan model

fan = UsdGeom.Xform.Define(stage, '/World/Fan')    
fan_references: Usd.References = fan.GetPrim().GetReferences()
fan_references.AddReference(
	assetPath= "./Assets/Fan.usd"
)

stage.Save()

Apply rotation to the oscillating joint

oscillator = stage.GetPrimAtPath("/World/Fan/Base/Oscillating_Joint")   
oscillator_xform = UsdGeom.Xformable(oscillator)    

translation_op = oscillator_xform.GetOrderedXformOps()[0]    

rotation_op = oscillator_xform.GetOrderedXformOps()[1]    

rotation_op.Set(Gf.Vec3d(0, -45, 0), 0)
rotation_op.Set(Gf.Vec3d(0, 45, 0), 71)
rotation_op.Set(Gf.Vec3d(0, -45, 0), 143)   

stage.Save()

Listing 6.3 Applying Cubic Interpolation to the Oscillating Animation.

def cubic_hermite(P0, P1, M0, M1, t):
	h00 = 2 * t**3 - 3 * t**2 + 1
	h10 = t**3 - 2 * t**2 + t
	h01 = -2 * t**3 + 3 * t**2
	h11 = t**3 - t**2
	return h00 * P0 + h10 * M0 + h01 * P1 + h11 * M1   

R0 = Gf.Vec3d(0, -45, 0)    
R1 = Gf.Vec3d(0, 45, 0)    
T0_rot = Gf.Vec3d(0, 15, 0)    
T1_rot = Gf.Vec3d(0, 15, 0)    

rotation_op = oscillator.GetAttribute("xformOp:rotateXYZ")    

first_half_rotations = []    

for frame in range(72):
	t = frame / 71.0    
	interpolated_rotation = cubic_hermite(R0, R1, T0_rot, T1_rot, t)    
	rotation_op.Set(interpolated_rotation, Usd.TimeCode(frame))    
	first_half_rotations.append(interpolated_rotation)    

for frame in range(72, 144):
	mirrored_rotation = first_half_rotations[143 - frame]    
	rotation_op.Set(mirrored_rotation, Usd.TimeCode(frame))    

stage.Save()

Animate the fan blades with full rotation around the z-axis

fan_blades = stage.GetPrimAtPath("/World/Fan/Base/Oscillating_Joint/Motor/Blades")    

xform = UsdGeom.Xformable(fan_blades) 
rotation_attr = xform.AddXformOp(UsdGeom.XformOp.TypeRotateZ, UsdGeom.XformOp.PrecisionFloat)    

start_frame = 0    
end_frame = 143 
total_rotations = 10 
fps = 24.0 

total_angle = total_rotations * 360    

rotation_attr.Set(0, start_frame)    
rotation_attr.Set(total_angle, end_frame)    

stage.Save()

Add camera animation

camera_path = Sdf.Path("/World/Camera")  
camera: UsdGeom.Camera = UsdGeom.Camera.Define(stage, camera_path)    

camera.GetFocalLengthAttr().Set(20)    

translate_op = camera.AddTranslateOp()    
translate_op.Set(Gf.Vec3d(0, 5, 100), 0)    
translate_op.Set(Gf.Vec3d(0, 35, 90), 143)

rotation_op = camera.AddRotateXYZOp()    
rotation_op.Set(Gf.Vec3d(12,2,0),0)    
rotation_op.Set(Gf.Vec3d(-10,1,0),143)

stage.Save()