def gather_node(blender_object, export_settings):
    if not __filter_node(blender_object, export_settings):
        return None

    node = gltf2_io.Node(
        camera=__gather_camera(blender_object, export_settings),
        children=__gather_children(blender_object, export_settings),
        extensions=__gather_extensions(blender_object, export_settings),
        extras=__gather_extras(blender_object, export_settings),
        matrix=__gather_matrix(blender_object, export_settings),
        mesh=__gather_mesh(blender_object, export_settings),
        name=__gather_name(blender_object, export_settings),
        rotation=None,
        scale=None,
        skin=__gather_skin(blender_object, export_settings),
        translation=None,
        weights=__gather_weights(blender_object, export_settings)
    )
    node.translation, node.rotation, node.scale = __gather_trans_rot_scale(blender_object, export_settings)

    if export_settings[gltf2_blender_export_keys.YUP]:
        if blender_object.type == 'LIGHT' and export_settings[gltf2_blender_export_keys.LIGHTS]:
            correction_node = __get_correction_node(blender_object, export_settings)
            correction_node.extensions = {"KHR_lights_punctual": node.extensions["KHR_lights_punctual"]}
            del node.extensions["KHR_lights_punctual"]
            node.children.append(correction_node)
        if blender_object.type == 'CAMERA' and export_settings[gltf2_blender_export_keys.CAMERAS]:
            correction_node = __get_correction_node(blender_object, export_settings)
            correction_node.camera = node.camera
            node.children.append(correction_node)
        node.camera = None

    return node
Exemple #2
0
def gather_node(vnode, export_settings):
    blender_object = vnode.blender_object

    skin = __gather_skin(vnode, blender_object, export_settings)
    node = gltf2_io.Node(
        camera=__gather_camera(blender_object, export_settings),
        children=__gather_children(vnode, blender_object, export_settings),
        extensions=__gather_extensions(blender_object, export_settings),
        extras=__gather_extras(blender_object, export_settings),
        matrix=__gather_matrix(blender_object, export_settings),
        mesh=__gather_mesh(vnode, blender_object, export_settings),
        name=__gather_name(blender_object, export_settings),
        rotation=None,
        scale=None,
        skin=skin,
        translation=None,
        weights=__gather_weights(blender_object, export_settings)
    )

    # If node mesh is skined, transforms should be ignored at import, so no need to set them here
    if node.skin is None:
        node.translation, node.rotation, node.scale = __gather_trans_rot_scale(vnode, export_settings)


    export_user_extensions('gather_node_hook', export_settings, node, blender_object)

    vnode.node = node

    if node.skin is not None:
        vnode.skin = skin

    return node
Exemple #3
0
def __gather_joints(blender_object, export_settings):
    # the skeletal hierarchy groups below a 'root' joint
    # TODO: add transform?
    torso = gltf2_io.Node(
        camera=None,
        children=[],
        extensions={},
        extras=None,
        matrix=[],
        mesh=None,
        name="Skeleton_" + blender_object.name,
        rotation=None,
        scale=None,
        skin=None,
        translation=None,
        weights=None
    )

    # build the hierarchy of nodes out of the bones
    for blender_bone in blender_object.pose.bones:
        torso.children.append(gltf2_blender_gather_joints.gather_joint(blender_bone, export_settings))

    # joints is a flat list containing all nodes belonging to the skin
    joints = []

    def __collect_joints(node):
        joints.append(node)
        for child in node.children:
            __collect_joints(child)
    __collect_joints(torso)

    return joints
def gather_joint_vnode(vnode, export_settings):
    """
    Generate a glTF2 node from a blender bone, as joints in glTF2 are simply nodes.

    :param blender_bone: a blender PoseBone
    :param export_settings: the settings for this export
    :return: a glTF2 node (acting as a joint)
    """
    vtree = export_settings['vtree']
    blender_object = vtree.nodes[vnode].blender_object
    blender_bone = vtree.nodes[vnode].blender_bone

    mat = vtree.nodes[
        vtree.nodes[vnode].parent_uuid].matrix_world.inverted_safe(
        ) @ vtree.nodes[vnode].matrix_world

    trans, rot, sca = mat.decompose()

    trans = __convert_swizzle_location(trans, export_settings)
    rot = __convert_swizzle_rotation(rot, export_settings)
    sca = __convert_swizzle_scale(sca, export_settings)

    translation, rotation, scale = (None, None, None)
    if trans[0] != 0.0 or trans[1] != 0.0 or trans[2] != 0.0:
        translation = [trans[0], trans[1], trans[2]]
    if rot[0] != 1.0 or rot[1] != 0.0 or rot[2] != 0.0 or rot[3] != 0.0:
        rotation = [rot[1], rot[2], rot[3], rot[0]]
    if sca[0] != 1.0 or sca[1] != 1.0 or sca[2] != 1.0:
        scale = [sca[0], sca[1], sca[2]]

    # traverse into children
    children = []

    for bone_uuid in [
            c for c in vtree.nodes[vnode].children
            if vtree.nodes[c].blender_type ==
            gltf2_blender_gather_tree.VExportNode.BONE
    ]:
        children.append(gather_joint_vnode(bone_uuid, export_settings))

    # finally add to the joints array containing all the joints in the hierarchy
    node = gltf2_io.Node(camera=None,
                         children=children,
                         extensions=None,
                         extras=__gather_extras(blender_bone, export_settings),
                         matrix=None,
                         mesh=None,
                         name=blender_bone.name,
                         rotation=rotation,
                         scale=scale,
                         skin=None,
                         translation=translation,
                         weights=None)

    export_user_extensions('gather_joint_hook', export_settings, node,
                           blender_bone)

    vtree.nodes[vnode].node = node

    return node
Exemple #5
0
def __gather_node(blender_object, library, blender_scene, dupli_object_parent,
                  export_settings):
    children = __gather_children(blender_object, blender_scene,
                                 export_settings)

    # If blender_scene is None, we are coming from animation export
    # Check to know if object is exported is already done, so we don't check
    # again if object is instanced in scene : this check was already done when exporting object itself
    if not __filter_node(blender_object, blender_scene, export_settings):
        if children:
            pass
        else:
            return None

    node = gltf2_io.Node(
        camera=__gather_camera(blender_object, export_settings),
        children=children,
        extensions=__gather_extensions(blender_object, export_settings),
        extras=__gather_extras(blender_object, export_settings),
        matrix=__gather_matrix(blender_object, export_settings),
        mesh=__gather_mesh(blender_object, library, export_settings),
        name=__gather_name(blender_object, export_settings),
        rotation=None,
        scale=None,
        skin=__gather_skin(blender_object, export_settings),
        translation=None,
        weights=__gather_weights(blender_object, export_settings))
    node.__blender_data = ('OBJECT', blender_object)

    # If node mesh is skined, transforms should be ignored at import, so no need to set them here
    # if node.skin is None:
    # While its not needed by the gltf2 spec, MSFS might still want to see it
    node.translation, node.rotation, node.scale = __gather_trans_rot_scale(
        blender_object, export_settings)

    if export_settings[gltf2_blender_export_keys.YUP]:
        # Checking node.extensions is making sure that the type of lamp is managed, and will be exported
        if blender_object.type == 'LIGHT' and export_settings[
                gltf2_blender_export_keys.LIGHTS] and node.extensions:
            correction_node = __get_correction_node(blender_object,
                                                    export_settings)
            correction_node.extensions = {
                "KHR_lights_punctual": node.extensions["KHR_lights_punctual"]
            }
            del node.extensions["KHR_lights_punctual"]
            node.children.append(correction_node)
        if blender_object.type == 'CAMERA' and export_settings[
                gltf2_blender_export_keys.CAMERAS]:
            correction_node = __get_correction_node(blender_object,
                                                    export_settings)
            correction_node.camera = node.camera
            node.children.append(correction_node)
        node.camera = None

    export_user_extensions('gather_node_hook', export_settings, node,
                           blender_object)

    return node
Exemple #6
0
def gather_joint(blender_bone, export_settings):
    """
    Generate a glTF2 node from a blender bone, as joints in glTF2 are simply nodes
    :param blender_bone: a blender PoseBone
    :param export_settings: the settings for this export
    :return: a glTF2 node (acting as a joint)
    """

    axis_basis_change = mathutils.Matrix.Identity(4)
    if export_settings['gltf_yup']:
        axis_basis_change = mathutils.Matrix(
            ((1.0, 0.0, 0.0, 0.0), (0.0, 0.0, 1.0, 0.0), (0.0, -1.0, 0.0, 0.0),
             (0.0, 0.0, 0.0, 1.0)))

    # extract bone transform
    if blender_bone.parent is None:
        correction_matrix_local = gltf2_blender_math.multiply(
            axis_basis_change, blender_bone.bone.matrix_local)
    else:
        correction_matrix_local = gltf2_blender_math.multiply(
            blender_bone.parent.bone.matrix_local.inverted(),
            blender_bone.bone.matrix_local)
    matrix_basis = blender_bone.matrix_basis
    if export_settings['gltf_bake_skins']:
        gltf2_io_debug.print_console("WARNING",
                                     "glTF bake skins not supported")
        # matrix_basis = blender_object.convert_space(blender_bone, blender_bone.matrix, from_space='POSE',
        #                                             to_space='LOCAL')
    trans, rot, sca = gltf2_blender_extract.decompose_transition(
        gltf2_blender_math.multiply(correction_matrix_local, matrix_basis),
        'JOINT', export_settings)
    translation, rotation, scale = (None, None, None)
    if trans[0] != 0.0 or trans[1] != 0.0 or trans[2] != 0.0:
        translation = [trans[0], trans[1], trans[2]]
    if rot[0] != 0.0 or rot[1] != 0.0 or rot[2] != 0.0 or rot[3] != 1.0:
        rotation = [rot[0], rot[1], rot[2], rot[3]]
    if sca[0] != 1.0 or sca[1] != 1.0 or sca[2] != 1.0:
        scale = [sca[0], sca[1], sca[2]]

    # traverse into children
    children = []
    for bone in blender_bone.children:
        children.append(gather_joint(bone, export_settings))

    # finally add to the joints array containing all the joints in the hierarchy
    return gltf2_io.Node(camera=None,
                         children=children,
                         extensions=None,
                         extras=None,
                         matrix=None,
                         mesh=None,
                         name=blender_bone.name,
                         rotation=rotation,
                         scale=scale,
                         skin=None,
                         translation=translation,
                         weights=None)
Exemple #7
0
def gather_joint(blender_object, blender_bone, export_settings):
    """
    Generate a glTF2 node from a blender bone, as joints in glTF2 are simply nodes.

    :param blender_bone: a blender PoseBone
    :param export_settings: the settings for this export
    :return: a glTF2 node (acting as a joint)
    """
    axis_basis_change = mathutils.Matrix.Identity(4)
    if export_settings[gltf2_blender_export_keys.YUP]:
        axis_basis_change = mathutils.Matrix(
            ((1.0, 0.0, 0.0, 0.0), (0.0, 0.0, 1.0, 0.0), (0.0, -1.0, 0.0, 0.0), (0.0, 0.0, 0.0, 1.0)))

    # extract bone transform
    if blender_bone.parent is None:
        correction_matrix_local = gltf2_blender_math.multiply(axis_basis_change, blender_bone.bone.matrix_local)
    else:
        correction_matrix_local = gltf2_blender_math.multiply(
            blender_bone.parent.bone.matrix_local.inverted(), blender_bone.bone.matrix_local)
    matrix_basis = blender_bone.matrix_basis
    trans, rot, sca = gltf2_blender_extract.decompose_transition(
        gltf2_blender_math.multiply(correction_matrix_local, matrix_basis), export_settings)
    translation, rotation, scale = (None, None, None)
    if trans[0] != 0.0 or trans[1] != 0.0 or trans[2] != 0.0:
        translation = [trans[0], trans[1], trans[2]]
    if rot[0] != 1.0 or rot[1] != 0.0 or rot[2] != 0.0 or rot[3] != 0.0:
        rotation = [rot[1], rot[2], rot[3], rot[0]]
    if sca[0] != 1.0 or sca[1] != 1.0 or sca[2] != 1.0:
        scale = [sca[0], sca[1], sca[2]]

    # traverse into children
    children = []

    if export_settings["gltf_def_bones"] is False:
        for bone in blender_bone.children:
            children.append(gather_joint(blender_object, bone, export_settings))
    else:
        _, children_, _ = gltf2_blender_gather_skins.get_bone_tree(None, blender_bone.id_data)
        if blender_bone.name in children_.keys():
            for bone in children_[blender_bone.name]:
                children.append(gather_joint(blender_object, blender_bone.id_data.pose.bones[bone], export_settings))

    # finally add to the joints array containing all the joints in the hierarchy
    return gltf2_io.Node(
        camera=None,
        children=children,
        extensions=None,
        extras=__gather_extras(blender_bone, export_settings),
        matrix=None,
        mesh=None,
        name=blender_bone.name,
        rotation=rotation,
        scale=scale,
        skin=None,
        translation=translation,
        weights=None
    )
Exemple #8
0
def gather_joint(blender_object, blender_bone, export_settings):
    """
    Generate a glTF2 node from a blender bone, as joints in glTF2 are simply nodes.

    :param blender_bone: a blender PoseBone
    :param export_settings: the settings for this export
    :return: a glTF2 node (acting as a joint)
    """
    translation, rotation, scale = __gather_trans_rot_scale(
        blender_object, blender_bone, export_settings)

    # traverse into children
    children = []

    if export_settings["gltf_def_bones"] is False:
        for bone in blender_bone.children:
            children.append(gather_joint(blender_object, bone,
                                         export_settings))
    else:
        _, children_, _ = gltf2_blender_gather_skins.get_bone_tree(
            None, blender_bone.id_data)
        if blender_bone.name in children_.keys():
            for bone in children_[blender_bone.name]:
                children.append(
                    gather_joint(blender_object,
                                 blender_bone.id_data.pose.bones[bone],
                                 export_settings))

    # finally add to the joints array containing all the joints in the hierarchy
    node = gltf2_io.Node(camera=None,
                         children=children,
                         extensions=None,
                         extras=__gather_extras(blender_bone, export_settings),
                         matrix=None,
                         mesh=None,
                         name=blender_bone.name,
                         rotation=rotation,
                         scale=scale,
                         skin=None,
                         translation=translation,
                         weights=None)
    node.__blender_data = ('BONE', blender_object, blender_bone.name)

    export_user_extensions('gather_joint_hook', export_settings, node,
                           blender_bone)

    return node
Exemple #9
0
def __gather_node(blender_object, blender_scene, export_settings):
    # If blender_scene is None, we are coming from animation export
    # Check to know if object is exported is already done, so we don't check
    # again if object is instanced in scene : this check was already done when exporting object itself
    if not __filter_node(blender_object, blender_scene, export_settings):
        return None

    node = gltf2_io.Node(
        camera=__gather_camera(blender_object, export_settings),
        children=__gather_children(blender_object, blender_scene,
                                   export_settings),
        extensions=__gather_extensions(blender_object, export_settings),
        extras=__gather_extras(blender_object, export_settings),
        matrix=__gather_matrix(blender_object, export_settings),
        mesh=__gather_mesh(blender_object, export_settings),
        name=__gather_name(blender_object, export_settings),
        rotation=None,
        scale=None,
        skin=__gather_skin(blender_object, export_settings),
        translation=None,
        weights=__gather_weights(blender_object, export_settings))

    # If node mesh is skined, transforms should be ignored at import, so no need to set them here
    if node.skin is None:
        node.translation, node.rotation, node.scale = __gather_trans_rot_scale(
            blender_object, export_settings)

    if export_settings[gltf2_blender_export_keys.YUP]:
        # Checking node.extensions is making sure that the type of lamp is managed, and will be exported
        if blender_object.type == 'LIGHT' and export_settings[
                gltf2_blender_export_keys.LIGHTS] and node.extensions:
            correction_node = __get_correction_node(blender_object,
                                                    export_settings)
            correction_node.extensions = {
                "KHR_lights_punctual": node.extensions["KHR_lights_punctual"]
            }
            del node.extensions["KHR_lights_punctual"]
            node.children.append(correction_node)
        if blender_object.type == 'CAMERA' and export_settings[
                gltf2_blender_export_keys.CAMERAS]:
            correction_node = __get_correction_node(blender_object,
                                                    export_settings)
            correction_node.camera = node.camera
            node.children.append(correction_node)
        node.camera = None

    return node
Exemple #10
0
def __get_correction_node(blender_object, export_settings):
    correction_quaternion = gltf2_blender_extract.convert_swizzle_rotation(
        Quaternion((1.0, 0.0, 0.0), math.radians(-90.0)), export_settings)
    correction_quaternion = [
        correction_quaternion[1], correction_quaternion[2],
        correction_quaternion[3], correction_quaternion[0]
    ]
    return gltf2_io.Node(camera=None,
                         children=None,
                         extensions=None,
                         extras=None,
                         matrix=None,
                         mesh=None,
                         name=blender_object.name + '_Orientation',
                         rotation=correction_quaternion,
                         scale=None,
                         skin=None,
                         translation=None,
                         weights=None)
Exemple #11
0
def gather_node(blender_object, export_settings):
    if not __filter_node(blender_object, export_settings):
        return None

    node = gltf2_io.Node(
        camera=__gather_camera(blender_object, export_settings),
        children=__gather_children(blender_object, export_settings),
        extensions=__gather_extensions(blender_object, export_settings),
        extras=__gather_extras(blender_object, export_settings),
        matrix=__gather_matrix(blender_object, export_settings),
        mesh=__gather_mesh(blender_object, export_settings),
        name=__gather_name(blender_object, export_settings),
        rotation=None,
        scale=None,
        skin=__gather_skin(blender_object, export_settings),
        translation=None,
        weights=__gather_weights(blender_object, export_settings))
    node.translation, node.rotation, node.scale = __gather_trans_rot_scale(
        blender_object, export_settings)

    return node
Exemple #12
0
def gather_joint(blender_object, blender_bone, export_settings):
    """
    Generate a glTF2 node from a blender bone, as joints in glTF2 are simply nodes.

    :param blender_bone: a blender PoseBone
    :param export_settings: the settings for this export
    :return: a glTF2 node (acting as a joint)
    """
    axis_basis_change = mathutils.Matrix.Identity(4)
    if export_settings[gltf2_blender_export_keys.YUP]:
        axis_basis_change = mathutils.Matrix(
            ((1.0, 0.0, 0.0, 0.0), (0.0, 0.0, 1.0, 0.0), (0.0, -1.0, 0.0, 0.0), (0.0, 0.0, 0.0, 1.0)))

    # extract bone transform
    if blender_bone.parent is None:
        correction_matrix_local = axis_basis_change @ blender_bone.bone.matrix_local
    else:
        correction_matrix_local = (
            blender_bone.parent.bone.matrix_local.inverted_safe() @
            blender_bone.bone.matrix_local
        )

    if (blender_bone.bone.use_inherit_rotation == False or blender_bone.bone.inherit_scale != "FULL") and blender_bone.parent != None:
        rest_mat = (blender_bone.parent.bone.matrix_local.inverted_safe() @ blender_bone.bone.matrix_local)
        matrix_basis = (rest_mat.inverted_safe() @ blender_bone.parent.matrix.inverted_safe() @ blender_bone.matrix)
    else:
        matrix_basis = blender_bone.matrix
        matrix_basis = blender_object.convert_space(pose_bone=blender_bone, matrix=matrix_basis, from_space='POSE', to_space='LOCAL')

    trans, rot, sca = (correction_matrix_local @ matrix_basis).decompose()
    translation, rotation, scale = (None, None, None)
    if trans[0] != 0.0 or trans[1] != 0.0 or trans[2] != 0.0:
        translation = [trans[0], trans[1], trans[2]]
    if rot[0] != 1.0 or rot[1] != 0.0 or rot[2] != 0.0 or rot[3] != 0.0:
        rotation = [rot[1], rot[2], rot[3], rot[0]]
    if sca[0] != 1.0 or sca[1] != 1.0 or sca[2] != 1.0:
        scale = [sca[0], sca[1], sca[2]]

    # traverse into children
    children = []

    if export_settings["gltf_def_bones"] is False:
        for bone in blender_bone.children:
            children.append(gather_joint(blender_object, bone, export_settings))
    else:
        _, children_, _ = gltf2_blender_gather_skins.get_bone_tree(None, blender_bone.id_data)
        if blender_bone.name in children_.keys():
            for bone in children_[blender_bone.name]:
                children.append(gather_joint(blender_object, blender_bone.id_data.pose.bones[bone], export_settings))

    # finally add to the joints array containing all the joints in the hierarchy
    node = gltf2_io.Node(
        camera=None,
        children=children,
        extensions=None,
        extras=__gather_extras(blender_bone, export_settings),
        matrix=None,
        mesh=None,
        name=blender_bone.name,
        rotation=rotation,
        scale=scale,
        skin=None,
        translation=translation,
        weights=None
    )

    export_user_extensions('gather_joint_hook', export_settings, node, blender_bone)

    return node
Exemple #13
0
def __gather_node(blender_object, library, blender_scene, dupli_object_parent,
                  export_settings):
    children = __gather_children(blender_object, blender_scene,
                                 export_settings)

    camera = None
    mesh = None
    skin = None
    weights = None

    # If blender_scene is None, we are coming from animation export
    # Check to know if object is exported is already done, so we don't check
    # again if object is instanced in scene : this check was already done when exporting object itself
    if not __filter_node(blender_object, blender_scene, export_settings):
        if children:
            # This node should be filtered out, but has un-filtered children present.
            # So, export this node, excluding its camera, mesh, skin, and weights.
            # The transformations and animations on this node will have visible effects on children.
            pass
        else:
            # This node is filtered out, and has no un-filtered children or descendants.
            return None
    else:
        # This node is being fully exported.
        camera = __gather_camera(blender_object, export_settings)
        mesh = __gather_mesh(blender_object, library, export_settings)
        skin = __gather_skin(blender_object, export_settings)
        weights = __gather_weights(blender_object, export_settings)

    node = gltf2_io.Node(
        camera=camera,
        children=children,
        extensions=__gather_extensions(blender_object, export_settings),
        extras=__gather_extras(blender_object, export_settings),
        matrix=__gather_matrix(blender_object, export_settings),
        mesh=mesh,
        name=__gather_name(blender_object, export_settings),
        rotation=None,
        scale=None,
        skin=skin,
        translation=None,
        weights=weights)

    # If node mesh is skined, transforms should be ignored at import, so no need to set them here
    if node.skin is None:
        node.translation, node.rotation, node.scale = __gather_trans_rot_scale(
            blender_object, export_settings)

    if export_settings[gltf2_blender_export_keys.YUP]:
        # Checking node.extensions is making sure that the type of lamp is managed, and will be exported
        if blender_object.type == 'LIGHT' and export_settings[
                gltf2_blender_export_keys.LIGHTS] and node.extensions:
            correction_node = __get_correction_node(blender_object,
                                                    export_settings)
            correction_node.extensions = {
                "KHR_lights_punctual": node.extensions["KHR_lights_punctual"]
            }
            del node.extensions["KHR_lights_punctual"]
            node.children.append(correction_node)
        if blender_object.type == 'CAMERA' and export_settings[
                gltf2_blender_export_keys.CAMERAS]:
            correction_node = __get_correction_node(blender_object,
                                                    export_settings)
            correction_node.camera = node.camera
            node.children.append(correction_node)
        node.camera = None

    export_user_extensions('gather_node_hook', export_settings, node,
                           blender_object)

    return node
    def add_neutral_bones(self):
        for n in [
                n for n in self.nodes.values()
                if n.armature is not None and n.blender_type == VExportNode.
                OBJECT and hasattr(self.nodes[n.armature], "need_neutral_bone")
        ]:  #all skin meshes objects where neutral bone is needed
            # First add a new node

            axis_basis_change = Matrix.Identity(4)
            if self.export_settings[gltf2_blender_export_keys.YUP]:
                axis_basis_change = Matrix(
                    ((1.0, 0.0, 0.0, 0.0), (0.0, 0.0, 1.0, 0.0),
                     (0.0, -1.0, 0.0, 0.0), (0.0, 0.0, 0.0, 1.0)))

            trans, rot, sca = axis_basis_change.decompose()
            translation, rotation, scale = (None, None, None)
            if trans[0] != 0.0 or trans[1] != 0.0 or trans[2] != 0.0:
                translation = [trans[0], trans[1], trans[2]]
            if rot[0] != 1.0 or rot[1] != 0.0 or rot[2] != 0.0 or rot[3] != 0.0:
                rotation = [rot[1], rot[2], rot[3], rot[0]]
            if sca[0] != 1.0 or sca[1] != 1.0 or sca[2] != 1.0:
                scale = [sca[0], sca[1], sca[2]]
            neutral_bone = gltf2_io.Node(camera=None,
                                         children=None,
                                         extensions=None,
                                         extras=None,
                                         matrix=None,
                                         mesh=None,
                                         name='neutral_bone',
                                         rotation=rotation,
                                         scale=scale,
                                         skin=None,
                                         translation=translation,
                                         weights=None)
            # Add it to child list of armature
            self.nodes[n.armature].node.children.append(neutral_bone)
            # Add it to joint list
            n.node.skin.joints.append(neutral_bone)

            # Need to add an InverseBindMatrix
            array = BinaryData.decode_accessor_internal(
                n.node.skin.inverse_bind_matrices)

            axis_basis_change = Matrix.Identity(4)
            if self.export_settings[gltf2_blender_export_keys.YUP]:
                axis_basis_change = Matrix(
                    ((1.0, 0.0, 0.0, 0.0), (0.0, 0.0, 1.0, 0.0),
                     (0.0, -1.0, 0.0, 0.0), (0.0, 0.0, 0.0, 1.0)))

            inverse_bind_matrix = (axis_basis_change @ self.nodes[
                n.armature].matrix_world_armature).inverted_safe()

            matrix = []
            for column in range(0, 4):
                for row in range(0, 4):
                    matrix.append(inverse_bind_matrix[row][column])

            array = np.append(array, np.array([matrix]), axis=0)
            binary_data = gltf2_io_binary_data.BinaryData.from_list(
                array.flatten(), gltf2_io_constants.ComponentType.Float)
            n.node.skin.inverse_bind_matrices = gltf2_blender_gather_accessors.gather_accessor(
                binary_data, gltf2_io_constants.ComponentType.Float,
                len(array.flatten()) //
                gltf2_io_constants.DataType.num_elements(
                    gltf2_io_constants.DataType.Mat4), None, None,
                gltf2_io_constants.DataType.Mat4, self.export_settings)