Beispiel #1
0
    def _get_usd_joint_hierarchy_name(self, gltf_joint, root_joints):
        if gltf_joint in self._joint_hierarchy_name_map:
            return GLTF2USDUtils.convert_to_usd_friendly_node_name(
                self._joint_hierarchy_name_map[gltf_joint])

        joint = gltf_joint
        joint_name_stack = [
            GLTF2USDUtils.convert_to_usd_friendly_node_name(joint.name)
        ]

        while joint.parent != None and joint not in root_joints:
            joint = joint.parent
            joint_name_stack.append(
                GLTF2USDUtils.convert_to_usd_friendly_node_name(joint.name))

        joint_name = ''
        while len(joint_name_stack) > 0:
            if joint_name:
                joint_name = '{0}/{1}'.format(joint_name,
                                              joint_name_stack.pop())
            else:
                joint_name = joint_name_stack.pop()

        self._joint_hierarchy_name_map[gltf_joint] = joint_name
        return GLTF2USDUtils.convert_to_usd_friendly_node_name(joint_name)
Beispiel #2
0
    def _create_usd_skeleton(self, gltf_skin, usd_xform, usd_joint_names):
        """Creates a USD skeleton from a glTF skin
        
        Arguments:
            gltf_skin {Skin} -- gltf skin
            usd_xform {Xform} -- USD Xform
        
        Returns:
            Skeleton -- USD skeleton
        """

        # create skeleton  
        root_joints = gltf_skin.root_joints
        root_joint_names = [GLTF2USDUtils.convert_to_usd_friendly_node_name(root_joint.name) for root_joint in root_joints]

        skeleton = None

        if len(root_joints) == 1:
            skeleton = UsdSkel.Skeleton.Define(self.stage, '{0}/{1}'.format(usd_xform.GetPath(), root_joint_names[0]))
        else:
            skeleton = UsdSkel.Skeleton.Define(self.stage, '{0}/{1}'.format(usd_xform.GetPath(), '__root__')) 

        gltf_bind_transforms = [Gf.Matrix4d(*xform).GetInverse() for xform in gltf_skin.get_inverse_bind_matrices()]
        gltf_rest_transforms = [GLTF2USDUtils.compute_usd_transform_matrix_from_gltf_node(joint) for joint in gltf_skin.get_joints()]
        if len(root_joints) > 1:
            matrix = Gf.Matrix4d()
            matrix.SetIdentity()

        skeleton.CreateJointsAttr().Set(usd_joint_names)
        skeleton.CreateBindTransformsAttr(gltf_bind_transforms)
        skeleton.CreateRestTransformsAttr(gltf_rest_transforms)

        return skeleton
Beispiel #3
0
    def _convert_node_to_xform(self, node, usd_xform):
        """Converts a glTF node to a USD transform node.

        Arguments:
            node {dict} -- glTF node
            node_index {int} -- glTF node index
            xform_name {str} -- USD xform name
        """
        xformPrim = UsdGeom.Xform.Define(
            self.stage, '{0}/{1}'.format(
                usd_xform.GetPath(),
                GLTF2USDUtils.convert_to_usd_friendly_node_name(node.name)))

        if self._node_has_animations(node):
            self._convert_animation_to_usd(node, xformPrim)
        else:
            xformPrim.AddTransformOp().Set(self._compute_rest_matrix(node))

        mesh = node.get_mesh()
        if mesh != None:
            usd_mesh = self._convert_mesh_to_xform(mesh, xformPrim, node)

        children = node.get_children()

        for child in children:
            self._convert_node_to_xform(child, xformPrim)
Beispiel #4
0
    def _convert_materials_to_preview_surface_new(self):
        """
        Converts the glTF materials to preview surfaces
        """
        self.usd_materials = []
        material_path_root = '/Materials'
        scope = UsdGeom.Scope.Define(self.stage, material_path_root)
        material_name_map = []

        for i, material in enumerate(self.gltf_loader.get_materials()):
            material_name = '{0}_index_{1}'.format(
                GLTF2USDUtils.convert_to_usd_friendly_node_name(
                    material.get_name()), i)
            #check for unique material name
            if material_name in material_name_map:
                count = 1
                new_material_name = '{0}_{1}'.format(material_name, count)

                while new_material_name in material_name_map:
                    count += 1
                    new_material_name = '{0}_{1}'.format(material_name, count)
                material_name = new_material_name

            material_name_map.append(material_name)
            usd_material = USDMaterial(self.stage, material_name, scope, i,
                                       self.gltf_loader)
            usd_material.convert_material_to_usd_preview_surface(
                material, self.output_dir, material_name)
            self.usd_materials.append(usd_material)
Beispiel #5
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)
Beispiel #6
0
    def _linear_interpolate_values(self, value0, value1, factor):
        if len(value0) == 3:
            one_minus_factor = 1 - factor
            #translation or scale interpolation
            return [(factor * value0[0] + (one_minus_factor * value1[0])),
                    (factor * value0[1] + (one_minus_factor * value1[1])),
                    (factor * value0[2] + (one_minus_factor * value1[2]))]

        elif len(value0) == 4:
            #quaternion interpolation
            result = GLTF2USDUtils.slerp(value0, value1, factor)
            return result
        else:
            raise Exception('unsupported value type')
Beispiel #7
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 == '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())

            # 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)
            skinBinding.CreateBlendShapesAttr(names)

            # Set the starting weights of each blendshape to the weights defined in the glTF primitive
            skelAnim.CreateBlendShapeWeightsAttr().Set(weights)
            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 = len(indices) / 3
        face_count = [3] * num_faces
        mesh.CreateFaceVertexCountsAttr(face_count)
        mesh.CreateFaceVertexIndicesAttr(indices)
Beispiel #8
0
 def test_convert_node_transform_to_rest_matrix(self):
     node = self.loader.get_nodes()[0]
     GLTF2USDUtils.compute_usd_transform_matrix_from_gltf_node(node)
Beispiel #9
0
 def test_convert_node_name_to_usd_friendly_name(self):
     node = self.loader.get_nodes()[0]
     GLTF2USDUtils.convert_to_usd_friendly_node_name(node.get_name())