Skip to article frontmatterSkip to article content

Chapter 8

8.1 Understanding Basic Physics

Set working directory

import os
new_directory = <'/your/path/to/Ch07'>
os.chdir(new_directory)

Open a stage

from pxr import Usd, UsdGeom, Gf, Sdf, UsdPhysics

usd_file_path ='./physics.usda'
stage = Usd.Stage.Open(usd_file_path)    

Print the path of mesh

for prim in stage.Traverse():    
    if UsdGeom.Mesh(prim):    
        print(prim.GetPath().pathString)   

8.1.1 Computing Bounding Boxes

Function to compute the bounding box (same in Chapter 5, Listing 5.4)

def compute_bounding_box(stage, prim_path):    
    prim = stage.GetPrimAtPath(prim_path)
    purposes = [UsdGeom.Tokens.default_]    
    bboxcache = UsdGeom.BBoxCache(Usd.TimeCode.Default(), purposes)    
    bboxes = bboxcache.ComputeWorldBound(prim)    
    min_point = bboxes.ComputeAlignedRange().GetMin()
    max_point = bboxes.ComputeAlignedRange().GetMax()    
    return min_point, max_point    

Compute the bounding box and set the Extent of the meshes

prim_paths = ['/World/Sphere/Sphere_mesh', '/World/Cube/Cube_mesh']
for path in prim_paths:    
    min_point, max_point = compute_bounding_box(stage, path)    
    mesh = UsdGeom.Mesh(stage.GetPrimAtPath(path))    
    mesh.CreateExtentAttr([min_point, max_point])    

stage.Save()

8.1.2 Applying Physical Properties

Add a rigid body to the cube and sphere

for path in prim_paths:    
    prim = stage.GetPrimAtPath(path)  
    UsdPhysics.RigidBodyAPI.Apply(prim)  

stage.Save()

Give a collider to the cube and sphere

for path in prim_paths:    
    prim = stage.GetPrimAtPath(path)    
    UsdPhysics.CollisionAPI.Apply(prim)    

stage.Save()

Add mesh collision to the sphere

sphere_mesh_path = '/World/Sphere/Sphere_mesh'
sphere_prim = stage.GetPrimAtPath(sphere_mesh_path)    

mesh_collision_api = UsdPhysics.MeshCollisionAPI.Apply(sphere_prim)    

mesh_collision_api.GetApproximationAttr().Set("boundingSphere")   

stage.Save()

Add mass to the sphere

mass_api = UsdPhysics.MassAPI.Apply(sphere_prim)    
mass_api.CreateMassAttr().Set(10000.0)    

stage.Save()

Add mass to the cube

cube_mesh_path = '/World/Cube/Cube_mesh'
cube_prim = stage.GetPrimAtPath(cube_mesh_path)    

mass_api = UsdPhysics.MassAPI.Apply(cube_prim)    
mass_api.CreateMassAttr().Set(100000.0)    

stage.Save()

8.1.3 Defining Physics Materials

Create and set the physics-specific attributes

from pxr import UsdShade   

physics_material = UsdShade.Material.Define(stage, "/World/PhysicsMaterial")   
physics_material_api = UsdPhysics.MaterialAPI.Apply(physics_material.GetPrim())   

physics_material_api.CreateStaticFrictionAttr().Set(0.9)	
physics_material_api.CreateDynamicFrictionAttr().Set(0.8)	
physics_material_api.CreateRestitutionAttr().Set(1.0)	

stage.Save()

Bind the physics material to the sphere prim

sphere_prim = stage.GetPrimAtPath("/World/Sphere/Sphere_mesh")	
sphere_prim.CreateRelationship("material:binding:physics").AddTarget(physics_material.GetPath())   

stage.Save()

Bind the physics material to the cube prim

cube_prim = stage.GetPrimAtPath("/World/Cube/Cube_mesh")    
cube_prim.CreateRelationship("material:binding:physics").AddTarget(physics_material.GetPath())    

stage.Save()

Edit physical attributes values

physics_material_api.GetStaticFrictionAttr().Set(0.1)    
physics_material_api.GetDynamicFrictionAttr().Set(0.05)    
physics_material_api.GetRestitutionAttr().Set(0.1)    

stage.Save()

Set the combination mode

physics_material_api.GetRestitutionAttr().Set(1.0)    

physics_material.GetPrim().CreateAttribute("physxMaterial:restitutionCombineMode", Sdf.ValueTypeNames.Token).Set("max")   
physics_material.GetPrim().CreateAttribute("physxMaterial:frictionCombineMode", Sdf.ValueTypeNames.Token).Set("min")    

stage.Save()

8.2.1 Building the Swinging Sticks

Setting working directory

import os
new_directory = <'/your/path/to/Ch07'>
os.chdir(new_directory)

Load the stage for Swing Sticks

from pxr import Usd, UsdGeom, Gf, UsdPhysics 

usd_file_path = './swinging_sticks.usda'
stage = Usd.Stage.Open(usd_file_path)    

Set RigidBody and Colliders on two sticks

prim_paths = ['/root/swing/stick1', '/root/swing/stick2']    
for path in prim_paths:    
    sticks = stage.GetPrimAtPath(path)  
    UsdPhysics.RigidBodyAPI.Apply(sticks)  
    UsdPhysics.CollisionAPI.Apply(sticks)   

Add a join to stick 1

revolute_joint1 = UsdPhysics.RevoluteJoint.Define(stage, "/root/swing/stick1/joint1") 

revolute_joint1.CreateBody0Rel().SetTargets(["/root/swing/support_fulcrum"])    
revolute_joint1.CreateBody1Rel().SetTargets(["/root/swing/stick1"])    
revolute_joint1.CreateAxisAttr(UsdGeom.Tokens.y)    

stage.Save()

Set the second joint to the end of stick1.

revolute_joint2 = UsdPhysics.RevoluteJoint.Define(stage, "/root/swing/stick2/joint2")  

revolute_joint2.CreateBody0Rel().SetTargets(["/root/swing/stick1"])    
revolute_joint2.CreateBody1Rel().SetTargets(["/root/swing/stick2"])    
revolute_joint2.CreateAxisAttr(UsdGeom.Tokens.y)    

joint2_prim = revolute_joint2.GetPrim() 
joint2_prim.GetAttribute("physics:localPos0").Set(Gf.Vec3d(0.038, -1.823, 0.54)) 

stage.Save()