Esempio n. 1
0
    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()
        if not gltf_skin:
            self.logger.warning('The glTF node has joints, but no skin associated with them')
        else:
            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())
                skeleton_skel_binding_api = UsdSkel.BindingAPI(skeleton)
                skeleton_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)
Esempio n. 2
0
    def testSkelWithoutBindPose(self):
        """
        Tests export of a Skeleton when a bindPose is not fully setup.
        """

        mayaFile = os.path.join(self.inputPath, "UsdExportSkeletonTest",
            "UsdExportSkeletonWithoutBindPose.ma")
        cmds.file(mayaFile, force=True, open=True)

        frameRange = [1, 5]
        usdFile = os.path.abspath('UsdExportSkeletonWithoutBindPose.usda')
        cmds.usdExport(mergeTransformAndShape=True, file=usdFile,
                       shadingMode='none', frameRange=frameRange,
                       exportSkels='auto')

        stage = Usd.Stage.Open(usdFile)

        skeleton = UsdSkel.Skeleton.Get(stage, '/cubeRig/skel/joint1')
        self.assertEqual(skeleton.GetBindTransformsAttr().Get(),
            Vt.Matrix4dArray([Gf.Matrix4d(1.0)]))
        self.assertEqual(skeleton.GetJointsAttr().Get(),
            Vt.TokenArray(['joint1']))
        self.assertEqual(skeleton.GetRestTransformsAttr().Get(),
            Vt.Matrix4dArray([Gf.Matrix4d(1.0)]))

        self.assertTrue(skeleton.GetPrim().HasAPI(UsdSkel.BindingAPI))
        skelBindingAPI = UsdSkel.BindingAPI(skeleton)
        self.assertTrue(skelBindingAPI)

        animSourcePrim = skelBindingAPI.GetAnimationSource()
        self.assertEqual(animSourcePrim.GetPath(),
            '/cubeRig/skel/joint1/Animation')
        animSource = UsdSkel.Animation(animSourcePrim)
        self.assertTrue(animSource)

        self.assertEqual(skeleton.GetJointsAttr().Get(),
            Vt.TokenArray(['joint1']))
        self.assertEqual(animSource.GetRotationsAttr().Get(),
            Vt.QuatfArray([Gf.Quatf(1.0, Gf.Vec3f(0.0))]))
        self.assertEqual(animSource.GetScalesAttr().Get(),
            Vt.Vec3hArray([Gf.Vec3h(1.0)]))
        self.assertEqual(
            animSource.GetTranslationsAttr().Get(Usd.TimeCode.Default()),
            Vt.Vec3fArray([Gf.Vec3f(5.0, 5.0, 0.0)]))

        self.assertEqual(
            animSource.GetTranslationsAttr().Get(1.0),
            Vt.Vec3fArray([Gf.Vec3f(0.0, 0.0, 0.0)]))
        self.assertEqual(
            animSource.GetTranslationsAttr().Get(2.0),
            Vt.Vec3fArray([Gf.Vec3f(1.25, 1.25, 0.0)]))
        self.assertEqual(
            animSource.GetTranslationsAttr().Get(3.0),
            Vt.Vec3fArray([Gf.Vec3f(2.5, 2.5, 0.0)]))
        self.assertEqual(
            animSource.GetTranslationsAttr().Get(4.0),
            Vt.Vec3fArray([Gf.Vec3f(3.75, 3.75, 0.0)]))
        self.assertEqual(
            animSource.GetTranslationsAttr().Get(5.0),
            Vt.Vec3fArray([Gf.Vec3f(5.0, 5.0, 0.0)]))
Esempio n. 3
0
    def test_JointInfluences(self):
        """Tests for helpers for getting/setting joint influences."""

        stage = Usd.Stage.CreateInMemory()
        gprim = stage.DefinePrim('/Model/Gprim')

        binding = UsdSkel.BindingAPI(gprim)

        indices = binding.CreateJointIndicesPrimvar(constant=False,
                                                    elementSize=3)
        assert indices
        assert indices.GetInterpolation() == UsdGeom.Tokens.vertex
        assert indices.GetElementSize() == 3

        weights = binding.CreateJointWeightsPrimvar(constant=True)
        assert weights
        assert weights.GetInterpolation() == UsdGeom.Tokens.constant

        # Should be able to re-create bindings with an alternate
        # interpolation and/or element size.
        weights = binding.CreateJointWeightsPrimvar(constant=False,
                                                    elementSize=3)
        assert weights
        assert weights.GetInterpolation() == UsdGeom.Tokens.vertex
        assert weights.GetElementSize() == 3

        assert binding.SetRigidJointInfluence(10, 0.5)
        indices = binding.GetJointIndicesPrimvar()
        weights = binding.GetJointWeightsPrimvar()
        assert indices.Get() == Vt.IntArray([10])
        assert weights.Get() == Vt.FloatArray([0.5])
Esempio n. 4
0
    def test_InstancedBlendShape(self):
        """Tests for correctness in the interpretation of instanced 
           blend shapes."""

        testFile = "populate.usda"
        stage = Usd.Stage.Open(testFile)
        cache = UsdSkel.Cache()
        skelRoot = UsdSkel.Root(stage.GetPrimAtPath("/SkelBinding"))
        self.assertTrue(cache.Populate(skelRoot,
                                       Usd.TraverseInstanceProxies()))

        # instance proxy mesh
        mesh = stage.GetPrimAtPath("/SkelBinding/Instance/Override")
        skelBinding = UsdSkel.BindingAPI(mesh)
        self.assertEqual(list(skelBinding.GetBlendShapesAttr().Get()),
                         ["override"])

        skel = skelBinding.GetSkeleton()
        skelq = cache.GetSkelQuery(skel)
        animq = skelq.GetAnimQuery()
        self.assertEqual(list(animq.GetBlendShapeOrder()),
                         ["override", "shape"])

        skinq = cache.GetSkinningQuery(mesh)
        self.assertTrue(skinq.HasBlendShapes())
        self.assertEqual(skelBinding.GetInheritedAnimationSource(),
                         stage.GetPrimAtPath("/Anim1"))

        # bug PRES-77530
        # because skelBinding.GetBlendShapesAttr().Get() and
        # animq.GetBlendShapeOrder() have different order,
        # the mapper should not be null.
        mapper = skinq.GetBlendShapeMapper()
        self.assertFalse(mapper.IsNull())
Esempio n. 5
0
    def _convert_primitive_to_mesh(self, gltf_primitive, usd_node, gltf_node,
                                   gltf_mesh):
        """
        Converts a glTF mesh primitive to a USD mesh

        Arguments:
            name {str} -- name of the primitive
            primitive {dict} -- glTF primitive
            usd_parent_node {str} -- USD parent xform
            node_index {int} -- glTF node index
            double_sided {bool} -- specifies if the primitive is double sided
        """
        parent_node = usd_node
        parent_path = parent_node.GetPath()
        attributes = gltf_primitive.get_attributes()
        skel_root = None
        targets = gltf_primitive.get_morph_targets()
        if 'JOINTS_0' in attributes or len(targets) > 0:
            skeleton_path = '{0}/{1}'.format(usd_node.GetPath(),
                                             'skeleton_root')
            skel_root = UsdSkel.Root.Define(self.stage, skeleton_path)
            parent_node = skel_root
            parent_path = parent_node.GetPath()
        mesh = UsdGeom.Mesh.Define(
            self.stage, '{0}/{1}'.format(
                parent_node.GetPath(),
                GLTF2USDUtils.convert_to_usd_friendly_node_name(
                    gltf_primitive.get_name())))
        mesh.CreateSubdivisionSchemeAttr().Set('none')

        material = gltf_primitive.get_material()
        if material != None:
            if material.is_double_sided():
                mesh.CreateDoubleSidedAttr().Set(True)

            usd_material = self.usd_materials[material.get_index()]
            UsdShade.MaterialBindingAPI(mesh).Bind(
                usd_material.get_usd_material())

        for attribute_name in attributes:
            attribute = attributes[attribute_name]
            if attribute_name == 'POSITION':
                override_prim = self.stage.OverridePrim(mesh.GetPath())
                override_prim.CreateAttribute(
                    'extent', Sdf.ValueTypeNames.Float3Array).Set(
                        [attribute.get_min_value(),
                         attribute.get_max_value()])
                mesh.CreatePointsAttr(attribute.get_data())

            if attribute_name == 'NORMAL':
                mesh.CreateNormalsAttr(attribute.get_data())

            if attribute_name == 'COLOR_0':
                prim_var = UsdGeom.PrimvarsAPI(mesh)
                data = attribute.get_data()
                if attribute.accessor_type == 'VEC4':
                    print(
                        'Vertex color alpha currently not supported.  Defaulting to vertex color without alpha.'
                    )
                    data = [
                        Gf.Vec3f(entry[0:3]) for entry in attribute.get_data()
                    ]

                colors = prim_var.CreatePrimvar('displayColor',
                                                Sdf.ValueTypeNames.Color3f,
                                                'vertex').Set(data)

            if attribute_name == 'TEXCOORD_0':
                data = attribute.get_data()
                invert_uvs = []
                for uv in data:
                    new_uv = (uv[0], 1 - uv[1])
                    invert_uvs.append(new_uv)
                prim_var = UsdGeom.PrimvarsAPI(mesh)
                uv = prim_var.CreatePrimvar('primvars:st0',
                                            Sdf.ValueTypeNames.TexCoord2fArray,
                                            'vertex')
                uv.Set(invert_uvs)

            if attribute_name == 'TEXCOORD_1':
                data = attribute.get_data()
                invert_uvs = []
                for uv in data:
                    new_uv = (uv[0], 1 - uv[1])
                    invert_uvs.append(new_uv)
                prim_var = UsdGeom.PrimvarsAPI(mesh)
                uv = prim_var.CreatePrimvar('primvars:st1',
                                            Sdf.ValueTypeNames.TexCoord2fArray,
                                            'vertex')
                uv.Set(invert_uvs)

            if attribute_name == 'JOINTS_0':
                self._convert_skin_to_usd(gltf_node, gltf_primitive,
                                          parent_node, mesh)

        weights = gltf_mesh.get_weights()
        if targets:
            skinBinding = UsdSkel.BindingAPI.Apply(mesh.GetPrim())

            skeleton = UsdSkel.Skeleton.Define(self.stage,
                                               '{0}/skel'.format(parent_path))

            # Create an animation for this mesh to hold the blendshapes
            skelAnim = UsdSkel.Animation.Define(
                self.stage, '{0}/skel/anim'.format(parent_path))

            # link the skeleton animation to skelAnim
            skinBinding.CreateAnimationSourceRel().AddTarget(
                skelAnim.GetPath())
            skeleton_skel_binding = UsdSkel.BindingAPI(skeleton)
            skeleton_skel_binding.CreateAnimationSourceRel().AddTarget(
                skelAnim.GetPath())

            # link the skeleton to skeleton
            skinBinding.CreateSkeletonRel().AddTarget(skeleton.GetPath())

            # Set blendshape names on the animation
            names = []
            for i, _ in enumerate(gltf_mesh.get_weights()):
                targets[i].get_name()
                blend_shape_name = GLTF2USDUtils.convert_to_usd_friendly_node_name(
                    targets[i].get_name())
                names.append(blend_shape_name)

            skelAnim.CreateBlendShapesAttr().Set(names)
            self._set_blendshape_weights(skelAnim, usd_node, gltf_node)
            skinBinding.CreateBlendShapesAttr(names)

            # Set the starting weights of each blendshape to the weights defined in the glTF primitive
            blend_shape_targets = skinBinding.CreateBlendShapeTargetsRel()

            # Define offsets for each blendshape, and add them as skel:blendShapes and skel:blendShapeTargets
            for i, name in enumerate(names):
                offsets = targets[i].get_attributes()['POSITION']
                blend_shape_name = '{0}/{1}'.format(mesh.GetPath(), name)

                # define blendshapes in the mesh
                blend_shape = UsdSkel.BlendShape.Define(
                    self.stage, blend_shape_name)
                blend_shape.CreateOffsetsAttr(offsets)
                blend_shape_targets.AddTarget(name)

        indices = gltf_primitive.get_indices()
        num_faces = int(len(indices) / 3)
        face_count = [3] * num_faces
        mesh.CreateFaceVertexCountsAttr(face_count)
        mesh.CreateFaceVertexIndicesAttr(indices)