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)
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
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)
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)
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)
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')
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)
def test_convert_node_transform_to_rest_matrix(self): node = self.loader.get_nodes()[0] GLTF2USDUtils.compute_usd_transform_matrix_from_gltf_node(node)
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())