def _convert_to_usd_matrix(self, matrix): """Converts a glTF matrix to a Usd Matrix Arguments: matrix {[type]} -- [description] Returns: [type] -- [description] """ return Gf.Matrix4d( matrix[0], matrix[1], matrix[2], matrix[3], matrix[4], matrix[5], matrix[6], matrix[7], matrix[8], matrix[9], matrix[10], matrix[11], matrix[12], matrix[13], matrix[14], matrix[15] )
def test_ComputeNarrowedFrustum(self): f = Gf.Frustum() f.projectionType = f.Orthographic f.Transform(Gf.Matrix4d(Gf.Vec4d(3,2,1,1))) narrowF = f.ComputeNarrowedFrustum(Gf.Vec2d(0, 0), Gf.Vec2d(0.1, 0.1)) self.assertTrue(Gf.IsClose(narrowF.window.min, Gf.Vec2d(-0.3, -0.2), 0.0001)) self.assertTrue(Gf.IsClose(narrowF.window.max, Gf.Vec2d(0.3, 0.2), 0.0001)) narrowF = f.ComputeNarrowedFrustum(Gf.Vec3d(0, 0, -1), Gf.Vec2d(0.1, 0.1)) self.assertTrue(Gf.IsClose(narrowF.window.min, Gf.Vec2d(-0.3, -0.2), 0.0001)) self.assertTrue(Gf.IsClose(narrowF.window.max, Gf.Vec2d(0.3, 0.2), 0.0001)) # Given a point behind the eye should get the same frustum back narrowF = f.ComputeNarrowedFrustum(Gf.Vec3d(0, 0, 1), Gf.Vec2d(0.1, 0.1)) self.assertTrue(Gf.IsClose(narrowF.window.min, Gf.Vec2d(-3.0,-2.0), 0.0001)) self.assertTrue(Gf.IsClose(narrowF.window.max, Gf.Vec2d(3.0,2.0), 0.0001))
def _convert_skin_to_usd(self, gltf_node, gltf_primitive, usd_node, usd_mesh): """Converts a glTF skin to a UsdSkel Arguments: gltf_node {dict} -- glTF node node_index {int} -- index of the glTF node usd_parent_node {UsdPrim} -- parent node of the usd node usd_mesh {[type]} -- [description] """ skel_binding_api = UsdSkel.BindingAPI(usd_mesh) gltf_skin = gltf_node.get_skin() gltf_joint_names = [GLTF2USDUtils.convert_to_usd_friendly_node_name(joint.name) for joint in gltf_skin.get_joints()] usd_joint_names = [Sdf.Path(self._get_usd_joint_hierarchy_name(joint, gltf_skin.root_joints)) for joint in gltf_skin.get_joints()] skeleton = self._create_usd_skeleton(gltf_skin, usd_node, usd_joint_names) skeleton_animation = self._create_usd_skeleton_animation(gltf_skin, skeleton, usd_joint_names) parent_path = usd_node.GetPath() bind_matrices = [] rest_matrices = [] skeleton_root = self.stage.GetPrimAtPath(parent_path) skel_binding_api = UsdSkel.BindingAPI(usd_mesh) skel_binding_api.CreateGeomBindTransformAttr(Gf.Matrix4d(((1,0,0,0),(0,1,0,0),(0,0,1,0),(0,0,0,1)))) skel_binding_api.CreateSkeletonRel().AddTarget(skeleton.GetPath()) if skeleton_animation: skel_binding_api.CreateAnimationSourceRel().AddTarget(skeleton_animation.GetPath()) bind_matrices = self._compute_bind_transforms(gltf_skin) primitive_attributes = gltf_primitive.get_attributes() if 'WEIGHTS_0' in primitive_attributes and 'JOINTS_0' in primitive_attributes: total_vertex_weights = primitive_attributes['WEIGHTS_0'].get_data() total_vertex_joints = primitive_attributes['JOINTS_0'].get_data() total_joint_indices = [] total_joint_weights = [] for joint_indices, weights in zip(total_vertex_joints, total_vertex_weights): for joint_index, weight in zip(joint_indices, weights): total_joint_indices.append(joint_index) total_joint_weights.append(weight) joint_indices_attr = skel_binding_api.CreateJointIndicesPrimvar(False, 4).Set(total_joint_indices) total_joint_weights = Vt.FloatArray(total_joint_weights) UsdSkel.NormalizeWeights(total_joint_weights, 4) joint_weights_attr = skel_binding_api.CreateJointWeightsPrimvar(False, 4).Set(total_joint_weights)
def _processCameraData(self, jsonData, cameraStage): # type: (dict, pxr.Usd.Stage) -> None """ Create a USD Camera in the given USD Stage from the given JSON camera definition. """ cameraFOV = jsonData.get('fov', ) cameraName = jsonData.get('name') cameraEyePosition = jsonData.get('eye') cameraFocalLength = jsonData.get('focalLength') # cameraCenterOfInterest = jsonData.get('centerOfInterest') # cameraLensRadius = jsonData.get('lensRadius') cameraUpVector = normalize(jsonData.get('up')) # cameraScreenWindow = jsonData.get('screenwindow') cameraRatio = jsonData.get('ratio') cameraLook = normalize(jsonData.get('look')) # Look at conversion: forwardVector = normalize([ cameraEyePosition[0] - cameraLook[0], cameraEyePosition[1] - cameraLook[1], cameraEyePosition[2] - cameraLook[2] ]) sideVector = crossProduct(cameraUpVector, forwardVector) transformMatrix = [ sideVector[0], sideVector[1], sideVector[2], 0, cameraUpVector[0], cameraUpVector[1], cameraUpVector[2], 0, forwardVector[0], forwardVector[1], forwardVector[2], 0, cameraEyePosition[0], cameraEyePosition[1], cameraEyePosition[2], 1 ] cameraPrimPath = cameraStage.GetDefaultPrim().GetPath().AppendChild( cameraName) usdCamera = UsdGeom.Camera.Define(cameraStage, cameraPrimPath) usdCamera.MakeMatrixXform().Set(Gf.Matrix4d(*transformMatrix)) usdCamera.GetProjectionAttr().Set(UsdGeom.Tokens.perspective) if cameraFocalLength is not None: usdCamera.GetFocalLengthAttr().Set(cameraFocalLength) if cameraRatio is not None and cameraFOV is not None: camera = usdCamera.GetCamera(cameraStage.GetStartTimeCode()) camera.SetPerspectiveFromAspectRatioAndFieldOfView( aspectRatio=cameraRatio, fieldOfView=cameraFOV, direction=Gf.Camera.FOVHorizontal) usdCamera.SetFromCamera(camera)
def testSkelRestXformsWithNoDagPose(self): """ Tests export of rest xforms when there is no dagPose node at all. """ mayaFile = os.path.join(self.inputPath, "UsdExportSkeletonTest", "UsdExportSkeletonNoDagPose.ma") cmds.file(mayaFile, force=True, open=True) usdFile = os.path.abspath('UsdExportSkeletonRestXformsWithNoDagPose.usda') cmds.select('skel_root') cmds.mayaUSDExport(mergeTransformAndShape=True, file=usdFile, shadingMode='none', exportSkels='auto', selection=True) stage = Usd.Stage.Open(usdFile) skeleton = UsdSkel.Skeleton.Get(stage, '/skel_root/joint1') self.assertEqual(skeleton.GetJointsAttr().Get(), Vt.TokenArray(['joint1', 'joint1/joint2', 'joint1/joint2/joint3', 'joint1/joint2/joint3/joint4'])) self.assertEqual( skeleton.GetBindTransformsAttr().Get(), Vt.Matrix4dArray([ Gf.Matrix4d( (-1, 0, 0, 0), (0, 1, 0, 0), (0, 0, -1, 0), (0, 0, 0, 1) ), Gf.Matrix4d( (0, -1, 0, 0), (-1, 0, 0, 0), (0, 0, -1, 0), (3, 0, 0, 1) ), Gf.Matrix4d( (0, -1, 0, 0), (0, 0, -1, 0), (1, 0, 0, 0), (3, 0, -2, 1) ), Gf.Matrix4d( (0, -1, 0, 0), (1, 0, 0, 0), (0, 0, 1, 0), (3, 0, -4, 1) ), ]) ) self.assertEqual( skeleton.GetRestTransformsAttr().Get(), Vt.Matrix4dArray([ Gf.Matrix4d( (-1, 0, 0, 0), (0, 1, 0, 0), (0, 0, -1, 0), (0, 0, 0, 1) ), Gf.Matrix4d( (0, -1, 0, 0), (1, 0, 0, 0), (0, 0, 1, 0), (-3, 0, 0, 1) ), Gf.Matrix4d( (1, 0, 0, 0), (0, 0, 1, 0), (0, -1, 0, 0), (0, 0, 2, 1) ), Gf.Matrix4d( (1, 0, 0, 0), (0, 0, 1, 0), (0, -1, 0, 0), (0, 2, 0, 1) ), ]) )
def test_Cube(self): stage = Usd.Stage.CreateInMemory() cube = UsdGeom.Cube.Define(stage, "/Foo") cube.CreateSizeAttr(4.0) # Verify the extent computation when no transform matrix is given. self.verifyExtent(cube, [(-2, -2, -2), (2, 2, 2)]) # Apply the identity matrix. This should be identical to the extent # computed with no transform. self.verifyExtent(cube, [(-2, -2, -2), (2, 2, 2)], Gf.Matrix4d(1.0)) # Apply an arbitrary transform matrix. self.verifyExtent( cube, [(-2.242468870104182, -1.2424688701041822, -0.12123443505209108), (4.242468870104182, 5.242468870104181, 3.121234435052091)], STRANGE_TRANSFORM)
def test_Constructors(self): self.assertIsInstance(Gf.Transform(), Gf.Transform), err("constructor") self.assertIsInstance( Gf.Transform(Gf.Vec3d(), Gf.Rotation(), Gf.Vec3d(), Gf.Vec3d(), Gf.Rotation()), Gf.Transform), err("constructor") # test GfMatrix4d constructor rotation = Gf.Rotation(Gf.Vec3d(0.5, 0.6, 0.7), 123) m = Gf.Matrix4d(1.0) m.SetRotate(rotation) t = Gf.Transform(m) tm = t.GetMatrix() tol = 0.001 self.assertTrue(Gf.IsClose(tm[0],m[0],tol) and \ Gf.IsClose(tm[1],m[1],tol) and \ Gf.IsClose(tm[2],m[2],tol) and \ Gf.IsClose(tm[3],m[3],tol), \ err("GfTransform(GfMatrix4d) constructor"))
def set_translate(prim, new_loc): properties = prim.GetPropertyNames() if "xformOp:translate" in properties: translate_attr = prim.GetAttribute("xformOp:translate") translate_attr.Set(new_loc) elif "xformOp:translation" in properties: translation_attr = prim.GetAttribute("xformOp:translate") translation_attr.Set(new_loc) elif "xformOp:transform" in properties: transform_attr = prim.GetAttribute("xformOp:transform") matrix = prim.GetAttribute("xformOp:transform").Get() matrix.SetTranslateOnly(new_loc) transform_attr.Set(matrix) else: xform = UsdGeom.Xformable(prim) xform_op = xform.AddXformOp(UsdGeom.XformOp.TypeTransform, UsdGeom.XformOp.PrecisionDouble, "") xform_op.Set(Gf.Matrix4d().SetTranslate(new_loc))
def compute(self, **kwargs): if not self.object: return None input_stage = self.get_input_link('Input', **kwargs) if not input_stage: return None if not input_stage.GetPseudoRoot().GetAllChildren(): return None depsgraph = bpy.context.evaluated_depsgraph_get() obj = self.object.evaluated_get(depsgraph) distribute_items = obj.data.vertices if self.method == 'VERTICES' else obj.data.polygons if not distribute_items: return None stage = self.cached_stage.create() UsdGeom.SetStageMetersPerUnit(stage, 1) UsdGeom.SetStageUpAxis(stage, UsdGeom.Tokens.z) for i, item in enumerate(distribute_items): root_xform = UsdGeom.Xform.Define( stage, f'/{Tf.MakeValidIdentifier(f"{self.name}_{i}")}') for prim in input_stage.GetPseudoRoot().GetAllChildren(): override_prim = stage.OverridePrim( root_xform.GetPath().AppendChild(prim.GetName())) override_prim.GetReferences().AddReference( input_stage.GetRootLayer().realPath, prim.GetPath()) trans = Matrix.Translation(item.co if self.method == 'VERTICES' else item.center) rot = item.normal.to_track_quat().to_matrix().to_4x4() transform = trans @ rot if self.object_transform: transform = obj.matrix_world @ transform UsdGeom.Xform.Get(stage, root_xform.GetPath()).MakeMatrixXform() root_xform.GetPrim().GetAttribute('xformOp:transform').Set( Gf.Matrix4d(transform.transposed())) return stage
def test_DecomposeRotation3(self): '''Test DecomposeRotation3, should be identical to zero Sw except it returns a 3-tuple. Minimally tested with and without hints as the functionality is more thoroughly tested in the zero Sw case above.''' rot = Gf.Matrix4d(-0.77657773110174733, 0.41334436580878597, -0.47547183177449759, 0.0, 0.53325734733674601, 0.029348545343396093, -0.8454438268729656, 0.0, -0.33550503583141722, -0.91010169659239692, -0.24321034680169412, 0.0, 0.0, 0.0, 0.0, 1.0) # No hints thetaTw, thetaFB, thetaLR = \ Gf.Rotation.DecomposeRotation3(rot, twAxis = Gf.Vec3d(0, 0, 1), fbAxis = Gf.Vec3d(1, 0, 0), lrAxis = Gf.Vec3d(0, 1, 0), handedness = 1) self.assertAlmostEqual(thetaTw, -1.641680, places=5) self.assertAlmostEqual(thetaFB, 1.998063, places=5) self.assertAlmostEqual(thetaLR, 0.943548, places=5) self.assertTrue( IsMatrixClose( ComposeRotation('XYZ', (thetaTw, thetaFB, thetaLR, 0.0)), rot)) # Hints variation 1 thetaTw, thetaFB, thetaLR = \ Gf.Rotation.DecomposeRotation3(rot, twAxis = Gf.Vec3d(0, 0, 1), fbAxis = Gf.Vec3d(1, 0, 0), lrAxis = Gf.Vec3d(0, 1, 0), handedness = 1, thetaTwHint = -2.0, thetaFBHint = 2, thetaLRHint = 1.0, useHint = True) self.assertAlmostEqual(thetaTw, -1.641680, places=5) self.assertAlmostEqual(thetaFB, 1.998063, places=5) self.assertAlmostEqual(thetaLR, 0.943548, places=5) self.assertTrue( IsMatrixClose( ComposeRotation('XYZ', (thetaTw, thetaFB, thetaLR, 0.0)), rot))
def test_ConstructFromMatrix(self): m = Gf.Matrix4d(0.9987016645043332, -0.035803686178599, -0.036236464677155, 0.0, 0.0362364646771555, 0.999278702502407, 0.011357524061459, 0.0, 0.0358036861785999, -0.012655859557126, 0.999278702502407, 0.0, 3.0 , -6.0 , 5.0 , 1.0) f = Gf.Frustum(m, Gf.Range2d(Gf.Vec2d(-0.22,-0.2), Gf.Vec2d(0.2, 0.33)), Gf.Range1d(20, 90), Gf.Frustum.Perspective) f = Gf.Frustum(m, Gf.Range2d(Gf.Vec2d(-0.22,-0.2), Gf.Vec2d(0.2, 0.33)), Gf.Range1d(20, 90), Gf.Frustum.Perspective) corners = f.ComputeCorners() results = (Gf.Vec3d( -2.255306906099, -9.58646139968125, -14.8715637017144), Gf.Vec3d( 6.133787075736, -9.88721236358150, -15.1759500050026), Gf.Vec3d( -1.871200380521, 1.00589284684426, -14.7511739466630), Gf.Vec3d( 6.517893601314, 0.70514188294401, -15.0555602499511), Gf.Vec3d(-20.648881077448, -22.13907629856565, -84.4220366577152), Gf.Vec3d( 17.102041840815, -23.49245563611677, -85.7917750225117), Gf.Vec3d(-18.920401712348, 25.52651781079917, -83.8802827599836), Gf.Vec3d( 18.830521205915, 24.17313847324806, -85.2500211247801)) self.assertEqual(len(corners), len(results)) for i in range(len(results)): self.assertTrue(Gf.IsClose(corners[i], results[i], 0.0001)) corners = f.ComputeCornersAtDistance(20) for i in range(len(corners)): self.assertTrue(Gf.IsClose(corners[i], results[i], 0.0001)) corners = f.ComputeCornersAtDistance(90) for i in range(len(corners)): self.assertTrue(Gf.IsClose(corners[i], results[i+4], 0.0001)) corners = f.ComputeCornersAtDistance((20 + 90) / 2.0) for i in range(len(corners)): self.assertTrue( Gf.IsClose(corners[i], (results[i] + results[i+4]) / 2.0, 0.0001))
def sync(root_prim, world: bpy.types.World, **kwargs): is_gl_mode = kwargs.get('is_gl_delegate', False) if is_gl_mode: # TODO export correct Dome light with texture for GL mode return # get the World IBL image data = WorldData.init_from_world(world) stage = root_prim.GetStage() if not data.cycles_ibl.image: # TODO create image from environment color data if no image used return # create Dome light xform = UsdGeom.Xform.Define(stage, root_prim.GetPath().AppendChild("_world")) obj_prim = xform.GetPrim() usd_light = UsdLux.DomeLight.Define( stage, obj_prim.GetPath().AppendChild(sdf_path(world.name))) usd_light.ClearXformOpOrder() usd_light.OrientToStageUpAxis() p = Sdf.AssetPath(data.cycles_ibl.image) usd_light.CreateTextureFileAttr(p) # set correct Dome light rotation matrix = np.identity(4) rotation = data.cycles_ibl.rotation euler = mathutils.Euler( (-rotation[0], -rotation[1] + np.pi, -rotation[2] - np.pi / 2)) rotation_matrix = np.array(euler.to_matrix(), dtype=np.float32) matrix[:3, :3] = rotation_matrix[:, :] xform.ClearXformOpOrder() xform.AddTransformOp().Set(Gf.Matrix4d(matrix))
def test_OneInstanceUnalignedData(self): stage = Usd.Stage.Open("test.usda") pi = UsdGeom.PointInstancer( stage.GetPrimAtPath("/OneInstanceUnalignedData")) # Test that unaligned positions/orientations are handled properly. baseTime = 3 tr = timeRange(baseTime) xformsArray = self.computeInstanceTransforms(pi, tr, baseTime) compares = [] for time, delta in tr: rotationTime = time - 2 velocityTime = time - 1 compares.append([ Gf.Matrix4d( Gf.Rotation(Gf.Vec3d(0, 0, 1), rotationTime * 36), Gf.Vec3d(velocityTime * 5, velocityTime * 10, velocityTime * 20)) ]) self.assertAllMatrixListsEqual(xformsArray, compares)
def build_transform(obj, frame=None): tfm_matrix = obj.Kinematics.Local.Transform.Matrix4 if frame is None else obj.Kinematics.Local.GetTransform2( frame).Matrix4 return Gf.Matrix4d( tfm_matrix.Value(0, 0), tfm_matrix.Value(0, 1), tfm_matrix.Value(0, 2), tfm_matrix.Value(0, 3), tfm_matrix.Value(1, 0), tfm_matrix.Value(1, 1), tfm_matrix.Value(1, 2), tfm_matrix.Value(1, 3), tfm_matrix.Value(2, 0), tfm_matrix.Value(2, 1), tfm_matrix.Value(2, 2), tfm_matrix.Value(2, 3), tfm_matrix.Value(3, 0), tfm_matrix.Value(3, 1), tfm_matrix.Value(3, 2), tfm_matrix.Value(3, 3), )
def test_PrestoRotatePivot(self): """ Test that simulates how the pivot position is taken into account in the presto transformable prim with transformType=Vectors. """ s = Usd.Stage.CreateInMemory() x = UsdGeom.Xform.Define(s, '/World') x.AddTranslateOp().Set(Gf.Vec3d(10., 0., 0.)) # Use token for 'pivot' x.AddTranslateOp(opSuffix='pivot', isInverseOp=False).Set(Gf.Vec3d(0, 10, 0)) x.AddRotateXYZOp().Set(Gf.Vec3f(60, 0, 30)) x.AddScaleOp().Set(Gf.Vec3f(2, 2, 2)) # Insert the inverse pivot. inverseTranslateOp = x.AddTranslateOp(opSuffix='pivot', isInverseOp=True) # Calling set on an inverseOp results in a coding error. self.assertEqual( x.GetXformOpOrderAttr().Get(), Vt.TokenArray(('xformOp:translate', 'xformOp:translate:pivot', 'xformOp:rotateXYZ', 'xformOp:scale', '!invert!xformOp:translate:pivot'))) xform = x.GetLocalTransformation(Usd.TimeCode.Default()) self._AssertCloseXf( xform, Gf.Matrix4d(1.7320508075688774, 1.0, 0.0, 0.0, -0.5, 0.8660254037844389, 1.7320508075688772, 0.0, 0.8660254037844385, -1.5, 1.0, 0.0, 15.0, 1.339745962155611, -17.32050807568877, 1.0))
def test_GetCamera(self): usdStage = Usd.Stage.CreateInMemory() usdCamera = UsdGeom.Camera.Define(usdStage, '/camera') # test fall-back values self._CheckValues(Gf.Camera(), usdCamera, 1.0) usdCamera.MakeMatrixXform().Set(Gf.Matrix4d(3.0)) usdCamera.GetProjectionAttr().Set(UsdGeom.Tokens.orthographic) usdCamera.GetHorizontalApertureAttr().Set(5.1) usdCamera.GetVerticalApertureAttr().Set(2.0) usdCamera.GetHorizontalApertureOffsetAttr().Set(-0.11) usdCamera.GetVerticalApertureOffsetAttr().Set(0.12) usdCamera.GetFocalLengthAttr().Set(28) usdCamera.GetClippingRangeAttr().Set(Gf.Vec2f(5, 15)) usdCamera.GetClippingPlanesAttr().Set([(1,2,3,4), (8,7,6,5)]) usdCamera.GetFStopAttr().Set(1.2) usdCamera.GetFocusDistanceAttr().Set(300) camera = usdCamera.GetCamera(1.0) # test assigned values self._CheckValues(camera, usdCamera, 1.0)
def test_PointInstancer(self): stage = Usd.Stage.Open("testPointInstancer.usda") pi = UsdGeom.PointInstancer(stage.GetPrimAtPath("/Instancer")) # Verify the extent computation when no transform matrix is given. self.verifyExtent(pi, [(-1, -1, -1), (3.5, 3.5, 3.5)]) # Verify the extent computation when no transform matrix is given. self.verifyExtent(pi, [(-1, -1, -1), (3.5, 3.5, 3.5)], Gf.Matrix4d(1.0)) # Apply an arbitrary transform matrix. Note that this is different from # the extent displayed in Usdview. If you open testPointInstancer.usda # and select /StrangeInstancer, you will see the box is larger than it # needs to be (it transforms the bounding box around the entire # PointInstancer, not the boxes for each instance like # ComputeExtentFromPlugins). If you select # /StrangeInstancerComputedExtent, it will display the (tighter) # computed extent used below. self.verifyExtent( pi, [(-1.3977774381637573, 0.3787655532360077, 0.689382791519165), (5.12123441696167, 6.12123441696167, 3.560617208480835)], STRANGE_TRANSFORM)
def test_PointBased(self): stage = Usd.Stage.Open("testPointBased.usda") pointBased = UsdGeom.PointBased(stage.GetPrimAtPath("/Points")) # Verify the extent computation when no transform matrix is given. self.verifyExtent(pointBased, [(0, 0, 0), (3.0, 2.0, 2.0)]) # Verify the extent computation when no transform matrix is given. self.verifyExtent(pointBased, [(0, 0, 0), (3.0, 2.0, 2.0)], Gf.Matrix4d(1.0)) # Apply an arbitrary transform matrix. Note that this is different from # the extent displayed in Usdview. If you open testPoints.usda and # select /StrangePoints, you will see the box is larger than it needs to # be (it transforms the bounding box around the points, not the points # themselves like ComputeExtentFromPlugins). If you select # /StrangePointsComputedExtent, it will display the (much tighter) # computed extent used below. self.verifyExtent( pointBased, [(0.3787655532360077, 2.0, 1.5), (4.4259724617004395, 3.609475612640381, 2.0058794021606445)], STRANGE_TRANSFORM)
def test_Points(self): stage = Usd.Stage.Open("testPoints.usda") points = UsdGeom.Points(stage.GetPrimAtPath("/Points")) # Verify the extent computation when no transform matrix is given. self.verifyExtent(points, [(-0.5, -0.5, -0.5), (3.25, 2.0, 2.25)]) # Verify the extent computation when no transform matrix is given. self.verifyExtent(points, [(-0.5, -0.5, -0.5), (3.25, 2.0, 2.25)], Gf.Matrix4d(1.0)) # Apply an arbitrary transform matrix. Note that this is different from # the extent displayed in Usdview. If you open testPoints.usda and # select /StrangePoints, you will see the box is larger than it needs to # be (it transforms the bounding box around the points, not the points # themselves like ComputeExtentFromPlugins). If you select # /StrangePointsComputedExtent, it will display the (much tighter) # computed extent used below. self.verifyExtent( points, [(0.18938279151916504, 1.189382791519165, 1.0946913957595825), (4.8312811851501465, 3.609475612640381, 2.041466236114502)], STRANGE_TRANSFORM)
def _write_influence_data(binding, mesh, cluster, binding_joints, maximum_influences, weights_getter): matrix = cmds.xform(mesh, matrix=True, worldSpace=True, q=True) binding.CreateGeomBindTransformAttr().Set(Gf.Matrix4d(*matrix)) indices, weights = _calculate_influences(mesh, cluster, binding_joints, maximum_influences, weights_getter) indices = Vt.IntArray(indices) weights = Vt.FloatArray(weights) # Reference: https://graphics.pixar.com/usd/docs/api/_usd_skel__schemas.html#UsdSkel_BindingAPI_StoringInfluences # Keep weights sorted and normalized for best performance # UsdSkel.NormalizeWeights(weights, len(binding_joints)) UsdSkel.SortInfluences(indices, weights, maximum_influences) indices_attribute = binding.CreateJointIndicesPrimvar( constant=False, elementSize=maximum_influences) indices_attribute.Set(indices) weights_attribute = binding.CreateJointWeightsPrimvar( constant=False, elementSize=maximum_influences) weights_attribute.Set(weights)
def test_Curves(self): stage = Usd.Stage.Open("testCurves.usda") curves = UsdGeom.Curves(stage.GetPrimAtPath("/Curves")) # Verify the extent computation when no transform matrix is given. self.verifyExtent(curves, [(-0.5, -0.5, -0.5), (3.5, 2.5, 2.5)]) # Verify the extent computation when no transform matrix is given. self.verifyExtent(curves, [(-0.5, -0.5, -0.5), (3.5, 2.5, 2.5)], Gf.Matrix4d(1.0)) # Apply an arbitrary transform matrix. Note that this is different from # the extent displayed in Usdview. If you open testPoints.usda and # select /StrangePoints, you will see the box is larger than it needs to # be (it transforms the bounding box around the curves, not the curves # themselves like ComputeExtentFromPlugins). If you select # /StrangePointsComputedExtent, it will display the (much tighter) # computed extent used below. self.verifyExtent( curves, [(-0.43185165524482727, 1.189382791519165, 1.0946913957595825), (5.236589431762695, 4.420092582702637, 2.4111881256103516)], STRANGE_TRANSFORM)
def testPivot(self): """ Tests that pivotPosition attribute doesn't interfere with the matrix that we get in maya when importing a usd file. """ def _usdToMayaPath(usdPath): return str(usdPath).replace('/', '|') from maya import cmds cmds.loadPlugin('pxrUsd') usdFile = './pivotTests.usda' from pxr import Usd, UsdGeom stage = Usd.Stage.Open(usdFile) xformCache = UsdGeom.XformCache() cmds.usdImport(file=os.path.abspath(usdFile), primPath='/World') usdPaths = [ '/World/anim/chars/SomeCharacter/Geom/Face/Eyes/LEye', '/World/anim/chars/SomeCharacter/Geom/Face/Eyes/LEye/Sclera_sbdv', '/World/anim/chars/SomeCharacter/Geom/Face/Eyes/REye/Sclera_sbdv', '/World/anim/chars/SomeCharacter/Geom/Hair/HairStandin/Hair/Hair_sbdv', '/World/anim/chars/SomeCharacter/Geom/Hair/HairStandin/Hair/HairFrontPiece_sbdv', ] for usdPath in usdPaths: usdMatrix = xformCache.GetLocalToWorldTransform( stage.GetPrimAtPath(usdPath)) mayaPath = _usdToMayaPath(usdPath) mayaMatrix = Gf.Matrix4d(*cmds.xform( mayaPath, query=True, matrix=True, worldSpace=True)) print 'testing matrix at', usdPath self.assertTrue( Gf.IsClose(usdMatrix.ExtractTranslation(), mayaMatrix.ExtractTranslation(), self.EPSILON))
def test_Methods(self): t1 = Gf.Transform() t2 = Gf.Transform() t1.SetMatrix(Gf.Matrix4d().SetRotate(Gf.Rotation( Gf.Vec3d(1, 1, 1), 60))) t2.SetMatrix(Gf.Matrix4d().SetRotate(Gf.Rotation( Gf.Vec3d(1, 1, 1), 60))) self.assertEqual(eval(repr(t1)), t1) self.assertEqual(t1, t2, err("equality")) t2.SetMatrix(Gf.Matrix4d().SetRotate(Gf.Rotation(Gf.Vec3d.ZAxis(), 60))) self.assertNotEqual(t1, t2, err("inequality")) t1 = Gf.Transform() t2 = Gf.Transform() t1.SetMatrix(Gf.Matrix4d().SetRotate(Gf.Rotation( Gf.Vec3d(1, 1, 1), 60))) t2.rotation = Gf.Rotation(Gf.Vec3d.YAxis(), 60) t1 *= t2 self.assertEqual(eval(repr(t1)), t1) self.assertTrue( Gf.IsClose(t1.rotation.axis, Gf.Vec3d(0.495572, 0.858356, 0.132788), 0.0001) and Gf.IsClose(t1.rotation.angle, 105.447, 0.0001), err("*=")) t1 = Gf.Transform() t2 = Gf.Transform() t1.SetMatrix(Gf.Matrix4d().SetRotate(Gf.Rotation( Gf.Vec3d(1, 1, 1), 60))) t2.rotation = Gf.Rotation(Gf.Vec3d.YAxis(), 60) t3 = t1 * t2 self.assertEqual(eval(repr(t3)), t3) self.assertTrue(Gf.IsClose(t3.rotation.axis, Gf.Vec3d(0.495572, 0.858356, 0.132788), 0.0001) and \ Gf.IsClose(t3.rotation.angle, 105.447, 0.0001), err("*=")) t1 = Gf.Transform() m = Gf.Matrix4d().SetScale(Gf.Vec3d(0, 1, 1)) t1.SetMatrix(m) self.assertTrue(Gf.IsClose(t1.scale, Gf.Vec3d(0.0, 1, 1), 1e-4), err("SetMatrix"))
def testSkelTransforms(self): """ Tests that the computed joint transforms in USD, when tarnsformed into world space, match the world space transforms of the Maya joints. """ mayaFile = os.path.join(self.inputPath, "UsdExportSkeletonTest", "UsdExportSkeleton.ma") cmds.file(mayaFile, force=True, open=True) # frameRange = [1, 30] frameRange = [1, 3] # TODO: The joint hierarchy intentionally includes non-joint nodes, # which are expected to be ignored. However, when we try to extract # restTransforms from the dagPose, the intermediate transforms cause # problems, since they are not members of the dagPose. As a result, # no dag pose is exported. Need to come up with a way to handle this # correctly in export. print("Expect warnings about invalid restTransforms") usdFile = os.path.abspath('UsdExportSkeleton.usda') cmds.usdExport(mergeTransformAndShape=True, file=usdFile, shadingMode='none', frameRange=frameRange, exportSkels='auto') stage = Usd.Stage.Open(usdFile) root = UsdSkel.Root.Get(stage, '/SkelChar') self.assertTrue(root) skelCache = UsdSkel.Cache() if Usd.GetVersion() > (0, 20, 8): skelCache.Populate(root, Usd.PrimDefaultPredicate) else: skelCache.Populate(root) skel = UsdSkel.Skeleton.Get(stage, '/SkelChar/Hips') self.assertTrue(skel) skelQuery = skelCache.GetSkelQuery(skel) self.assertTrue(skelQuery) xfCache = UsdGeom.XformCache() for frame in range(*frameRange): cmds.currentTime(frame, edit=True) xfCache.SetTime(frame) skelLocalToWorld = xfCache.GetLocalToWorldTransform( skelQuery.GetPrim()) usdJointXforms = skelQuery.ComputeJointSkelTransforms(frame) for joint, usdJointXf in zip(skelQuery.GetJointOrder(), usdJointXforms): usdJointWorldXf = usdJointXf * skelLocalToWorld selList = OM.MSelectionList() selList.add(Sdf.Path(joint).name) dagPath = selList.getDagPath(0) mayaJointWorldXf = Gf.Matrix4d(*dagPath.inclusiveMatrix()) self.assertTrue( Gf.IsClose(mayaJointWorldXf, usdJointWorldXf, 1e-5))
def _MMatrixToGf(mx): gfmx = Gf.Matrix4d() for i in range(4): for j in range(4): gfmx[i][j] = mx[i * 4 + j] return gfmx
def test_ScalarRotateOps(self): s = Usd.Stage.CreateInMemory() x = UsdGeom.Xform.Define(s, '/X') x.AddRotateXOp().Set(45.) xformX = x.GetLocalTransformation(Usd.TimeCode.Default()) self._AssertCloseXf(xformX, Gf.Matrix4d(1.0, 0.0, 0.0, 0.0, 0.0, 0.7071067811865475, 0.7071067811865476, 0.0, 0.0, -0.7071067811865476, 0.7071067811865475, 0.0, 0.0, 0.0, 0.0, 1.0)) self.assertEqual(x.GetXformOpOrderAttr().Get(), Vt.TokenArray(('xformOp:rotateX', ))) y = UsdGeom.Xform.Define(s, '/Y') y.AddRotateYOp().Set(90.) xformY = y.GetLocalTransformation(Usd.TimeCode.Default()) self._AssertCloseXf(xformY, Gf.Matrix4d(0, 0.0, -1.0, 0.0, 0.0, 1.0, 0.0, 0.0, 1.0, 0.0, 0, 0.0, 0.0, 0.0, 0.0, 1.0)) self.assertEqual(y.GetXformOpOrderAttr().Get(), Vt.TokenArray(('xformOp:rotateY', ))) z = UsdGeom.Xform.Define(s, '/Z') z.AddRotateZOp().Set(30.) xformZ = z.GetLocalTransformation(Usd.TimeCode.Default()) self._AssertCloseXf(xformZ, Gf.Matrix4d(0.866025403784439, 0.5, 0, 0, -0.5, 0.866025403784439, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1)) self.assertEqual(z.GetXformOpOrderAttr().Get(), Vt.TokenArray(('xformOp:rotateZ', ))) xy = UsdGeom.Xform.Define(s, '/XY') xy.AddRotateYOp().Set(90.) xy.AddRotateXOp().Set(45.) xformXY = xy.GetLocalTransformation(Usd.TimeCode.Default()) self._AssertCloseXf(xformXY, Gf.Matrix4d(0.0, 0.0, -1.0, 0.0, 0.7071067811865476, 0.7071067811865475, 0.0, 0.0, 0.7071067811865475, -0.7071067811865476, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0)) self.assertEqual(xy.GetXformOpOrderAttr().Get(), Vt.TokenArray(('xformOp:rotateY', 'xformOp:rotateX'))) yz = UsdGeom.Xform.Define(s, '/YZ') yz.AddRotateZOp().Set(30.) yz.AddRotateYOp().Set(90.) xformYZ = yz.GetLocalTransformation(Usd.TimeCode.Default()) self._AssertCloseXf(xformYZ, Gf.Matrix4d(0.0, 0.0, -1.0, 0.0, -0.5, 0.8660254037844387, 0.0, 0.0, 0.8660254037844387, 0.5, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0)) self.assertEqual(yz.GetXformOpOrderAttr().Get(), Vt.TokenArray(('xformOp:rotateZ', 'xformOp:rotateY'))) zx = UsdGeom.Xform.Define(s, '/ZX') zx.AddRotateXOp().Set(45.) zx.AddRotateZOp().Set(30.) xformZX = zx.GetLocalTransformation(Usd.TimeCode.Default()) self._AssertCloseXf(xformZX, Gf.Matrix4d(0.8660254037844387, 0.3535533905932737, 0.35355339059327373, 0.0, -0.5, 0.6123724356957945, 0.6123724356957946, 0.0, 0.0, -0.7071067811865476, 0.7071067811865475, 0.0, 0.0, 0.0, 0.0, 1.0)) self.assertEqual(zx.GetXformOpOrderAttr().Get(), Vt.TokenArray(('xformOp:rotateX', 'xformOp:rotateZ')))
def test_VaryingPrecisionOps(self): s = Usd.Stage.CreateInMemory() x1 = UsdGeom.Xform.Define(s, '/World') halfRotOp = x1.AddRotateXYZOp(precision=UsdGeom.XformOp.PrecisionHalf, opSuffix='Half') self.assertEqual(halfRotOp.GetPrecision(), UsdGeom.XformOp.PrecisionHalf) halfRotOp.Set(Gf.Vec3h(0.0, 0.0, 60.0)) doubleRotOp = x1.AddRotateXYZOp(precision=UsdGeom.XformOp.PrecisionDouble, opSuffix='Double') self.assertEqual(doubleRotOp.GetPrecision(), UsdGeom.XformOp.PrecisionDouble) doubleRotOp.Set(Gf.Vec3d(0.0, 45.123456789, 0.0)) floatRotOp = x1.AddRotateXYZOp(opSuffix='Float') self.assertEqual(floatRotOp.GetPrecision(), UsdGeom.XformOp.PrecisionFloat) floatRotOp.Set(Gf.Vec3f(30.0, 0.0, 0.0)) self.assertEqual(x1.GetXformOpOrderAttr().Get(), Vt.TokenArray(('xformOp:rotateXYZ:Half', 'xformOp:rotateXYZ:Double', 'xformOp:rotateXYZ:Float'))) xform1 = x1.GetLocalTransformation(Usd.TimeCode.Default()) x2 = UsdGeom.Xform.Define(s, '/World2') rotOp = x2.AddRotateXYZOp(precision=UsdGeom.XformOp.PrecisionDouble).Set(Gf.Vec3d(30.0, 45.123456789, 60.0)) xform2 = x2.GetLocalTransformation(Usd.TimeCode.Default()) # Everything gets converted to double internally, so the xforms computed # must be equal. self.assertEqual(xform1, xform2) x3 = UsdGeom.Xform.Define(s, '/World3') quatd = Gf.Quatd(1., Gf.Vec3d(2., 3., 4.)).GetNormalized() quatf = Gf.Quatf(2., Gf.Vec3f(3., 4., 5.)).GetNormalized() quath = Gf.Quath(3., Gf.Vec3h(4., 5., 6.)).GetNormalized() defaultOrientOp = x3.AddOrientOp().Set(quatf) floatOrientOp = x3.AddOrientOp(precision=UsdGeom.XformOp.PrecisionFloat, opSuffix='Float') floatOrientOp.Set(quatf) doubleOrientOp = x3.AddOrientOp(precision=UsdGeom.XformOp.PrecisionDouble, opSuffix='Double') doubleOrientOp.Set(quatd) halfOrientOp = x3.AddOrientOp(precision=UsdGeom.XformOp.PrecisionHalf, opSuffix='Half') halfOrientOp.Set(quath) # Cannot set a quatd on an op that is of precision float. with self.assertRaises(RuntimeError): floatOrientOp.Set(quatd) xform3 = x3.GetLocalTransformation(Usd.TimeCode.Default()) self._AssertCloseXf(xform3, Gf.Matrix4d(-0.27080552040616, -0.120257027227524, 0.955092988938746, 0, 0.95202181574436, 0.113459757051953, 0.284220593688289, 0, -0.14254414216081, 0.986237867318078, 0.0837617848635551, 0, 0, 0, 0, 1))
def RotMatrix(vec, angle): return Gf.Matrix4d(1.0).SetRotate(Gf.Rotation(vec, angle))
def test_AliasedTypes(self): # A list of value, type and the corresponding basic type. validAliasValues = [ # Color types (Gf.Vec3d(1, 2, 3), 'color3d', 'double3'), (Gf.Vec3f(1, 2, 3), 'color3f', 'float3'), (Gf.Vec3h(1, 2, 3), 'color3h', 'half3'), (Gf.Vec4d(1, 2, 3, 4), 'color4d', 'double4'), (Gf.Vec4f(1, 2, 3, 4), 'color4f', 'float4'), (Gf.Vec4h(1, 2, 3, 4), 'color4h', 'half4'), (Vt.Vec3dArray(), 'color3d[]', 'double3[]'), (Vt.Vec3fArray(), 'color3f[]', 'float3[]'), (Vt.Vec3hArray(), 'color3h[]', 'half3[]'), (Vt.Vec4dArray(), 'color4d[]', 'double4[]'), (Vt.Vec4fArray(), 'color4f[]', 'float4[]'), (Vt.Vec4hArray(), 'color4h[]', 'half4[]'), # Point types (Gf.Vec3d(1, 2, 3), 'point3d', 'double3'), (Gf.Vec3f(1, 2, 3), 'point3f', 'float3'), (Gf.Vec3h(1, 2, 3), 'point3h', 'half3'), (Vt.Vec3dArray(), 'point3d[]', 'double3[]'), (Vt.Vec3fArray(), 'point3f[]', 'float3[]'), (Vt.Vec3hArray(), 'point3h[]', 'half3[]'), # Normal types (Gf.Vec3d(1, 2, 3), 'normal3d', 'double3'), (Gf.Vec3f(1, 2, 3), 'normal3f', 'float3'), (Gf.Vec3h(1, 2, 3), 'normal3h', 'half3'), (Vt.Vec3dArray(), 'normal3d[]', 'double3[]'), (Vt.Vec3fArray(), 'normal3f[]', 'float3[]'), (Vt.Vec3hArray(), 'normal3h[]', 'half3[]'), # Vector types (Gf.Vec3d(1, 2, 3), 'vector3d', 'double3'), (Gf.Vec3f(1, 2, 3), 'vector3f', 'float3'), (Gf.Vec3h(1, 2, 3), 'vector3h', 'half3'), (Vt.Vec3dArray(), 'vector3d[]', 'double3[]'), (Vt.Vec3fArray(), 'vector3f[]', 'float3[]'), (Vt.Vec3hArray(), 'vector3h[]', 'half3[]'), # Frame type (Gf.Matrix4d(3), 'frame4d', 'matrix4d'), #Texture Coordinate type (Gf.Vec2d(1, 2), 'texCoord2d', 'double2'), (Gf.Vec2f(1, 2), 'texCoord2f', 'float2'), (Gf.Vec2h(1, 2), 'texCoord2h', 'half2'), (Gf.Vec3d(1, 2, 3), 'texCoord3d', 'double3'), (Gf.Vec3f(1, 2, 3), 'texCoord3f', 'float3'), (Gf.Vec3h(1, 2, 3), 'texCoord3h', 'half3'), (Vt.Vec2dArray(), 'texCoord2d[]', 'double2[]'), (Vt.Vec2fArray(), 'texCoord2f[]', 'float2[]'), (Vt.Vec2hArray(), 'texCoord2h[]', 'half2[]'), (Vt.Vec3dArray(), 'texCoord3d[]', 'double3[]'), (Vt.Vec3fArray(), 'texCoord3f[]', 'float3[]'), (Vt.Vec3hArray(), 'texCoord3h[]', 'half3[]') ] for value, typeName, baseTypeName in validAliasValues: self.assertTrue(Sdf.ValueHasValidType(value)) self.assertEqual(Sdf.GetValueTypeNameForValue(value), baseTypeName) self._TestRoundTrippingValue(typeName, value)
def test_TransformCompositionAndDecomposition(self): """ Tests UsdSkelMakeTransform(), UsdSkelDecomposeTransform() and their array forms. """ random.seed(0) count = 100 # Make some random transforms. translations = RandomTranslations(count) rotations = RandomRotations(count) scales = RandomScales(count) xforms = UsdSkel.MakeTransforms(translations, rotations, scales) assert xforms xformsBuiltIndividually = Vt.Matrix4dArray( [UsdSkel.MakeTransform(translations[i], rotations[i], scales[i]) for i in range(count)]) self.assertArrayIsClose(xforms, xformsBuiltIndividually) # Decompose back into components. decomposedComponents = UsdSkel.DecomposeTransforms(xforms) assert decomposedComponents decomposedTranslations,_,_ = decomposedComponents self.assertArrayIsClose(translations, decomposedTranslations) # Make sure the non-array decomposition matches. for i,xf in enumerate(xforms): t,_,_ = UsdSkel.DecomposeTransform(xf) self.assertTrue(Gf.IsClose(t, translations[i],1e-5)) # We can't really directly compare the decomposed rotations and scales # against the original components used to build our matrices: # Decomposition might produce different scales and rotations, but # which still give the same composed matrix result. # Instead, we rebuild xforms and validate that they give us the # xforms that the components were decomposed from. rebuiltXforms = UsdSkel.MakeTransforms(*decomposedComponents) assert rebuiltXforms self.assertArrayIsClose(xforms, rebuiltXforms) # And rebuilding each matrix individually... rebuiltXforms = Vt.Matrix4dArray( [UsdSkel.MakeTransform(*UsdSkel.DecomposeTransform(xf)) for xf in xforms]) self.assertArrayIsClose(xforms, rebuiltXforms) # Decomposing singular matrices should fail! with self.assertRaises(Tf.ErrorException): print("expect a warning about decomposing a singular matrix") UsdSkel.DecomposeTransform(Gf.Matrix4d(0)) with self.assertRaises(Tf.ErrorException): UsdSkel.DecomposeTransforms( Vt.Matrix4dArray([Gf.Matrix4d(1), Gf.Matrix4d(0)]))