Пример #1
0
def __gather_indices(blender_primitive, blender_mesh, modifiers,
                     export_settings):
    indices = blender_primitive.get('indices')
    if indices is None:
        return None

    # NOTE: Values used by some graphics APIs as "primitive restart" values are disallowed.
    # Specifically, the values 65535 (in UINT16) and 4294967295 (in UINT32) cannot be used as indices.
    # https://github.com/KhronosGroup/glTF/issues/1142
    # https://github.com/KhronosGroup/glTF/pull/1476/files
    # Also, UINT8 mode is not supported:
    # https://github.com/KhronosGroup/glTF/issues/1471
    max_index = indices.max()
    if max_index < 65535:
        component_type = gltf2_io_constants.ComponentType.UnsignedShort
        indices = indices.astype(np.uint16, copy=False)
    elif max_index < 4294967295:
        component_type = gltf2_io_constants.ComponentType.UnsignedInt
        indices = indices.astype(np.uint32, copy=False)
    else:
        print_console(
            'ERROR', 'A mesh contains too many vertices (' + str(max_index) +
            ') and needs to be split before export.')
        return None

    element_type = gltf2_io_constants.DataType.Scalar
    binary_data = gltf2_io_binary_data.BinaryData(indices.tobytes())
    return gltf2_blender_gather_accessors.gather_accessor(
        binary_data, component_type, len(indices), None, None, element_type,
        export_settings)
def __gather_input(channels: typing.Tuple[bpy.types.FCurve],
                   blender_object_if_armature: typing.Optional[bpy.types.Object],
                   non_keyed_values: typing.Tuple[typing.Optional[float]],
                   bake_bone: typing.Union[str, None],
                   bake_channel: typing.Union[str, None],
                   bake_range_start,
                   bake_range_end,
                   action_name,
                   driver_obj,
                   export_settings
                   ) -> gltf2_io.Accessor:
    """Gather the key time codes."""
    keyframes = gltf2_blender_gather_animation_sampler_keyframes.gather_keyframes(blender_object_if_armature,
                                                                                  channels,
                                                                                  non_keyed_values,
                                                                                  bake_bone,
                                                                                  bake_channel,
                                                                                  bake_range_start,
                                                                                  bake_range_end,
                                                                                  action_name,
                                                                                  driver_obj,
                                                                                  export_settings)
    times = [k.seconds for k in keyframes]

    return gltf2_blender_gather_accessors.gather_accessor(
        gltf2_io_binary_data.BinaryData.from_list(times, gltf2_io_constants.ComponentType.Float),
        gltf2_io_constants.ComponentType.Float,
        len(times),
        tuple([max(times)]),
        tuple([min(times)]),
        gltf2_io_constants.DataType.Scalar,
        export_settings
    )
def __gather_input(channels: typing.Tuple[bpy.types.FCurve],
                   blender_obj_uuid: str, is_armature: bool,
                   non_keyed_values: typing.Tuple[typing.Optional[float]],
                   bake_bone: typing.Union[str, None],
                   bake_channel: typing.Union[str, None], bake_range_start,
                   bake_range_end, force_range: bool, action_name,
                   driver_obj_uuid, node_channel_is_animated: bool,
                   export_settings) -> gltf2_io.Accessor:
    """Gather the key time codes."""
    keyframes, is_baked = gltf2_blender_gather_animation_sampler_keyframes.gather_keyframes(
        blender_obj_uuid, is_armature, channels, non_keyed_values, bake_bone,
        bake_channel, bake_range_start, bake_range_end, force_range,
        action_name, driver_obj_uuid, node_channel_is_animated,
        export_settings)
    if keyframes is None:
        # After check, no need to animation this node
        return None
    times = [k.seconds for k in keyframes]

    return gltf2_blender_gather_accessors.gather_accessor(
        gltf2_io_binary_data.BinaryData.from_list(
            times, gltf2_io_constants.ComponentType.Float),
        gltf2_io_constants.ComponentType.Float, len(times),
        tuple([max(times)]), tuple([min(times)]),
        gltf2_io_constants.DataType.Scalar, export_settings)
def __gather_indices(blender_primitive, blender_mesh, modifiers, export_settings):
    indices = blender_primitive['indices']

    # NOTE: Values used by some graphics APIs as "primitive restart" values are disallowed.
    # Specifically, the values 65535 (in UINT16) and 4294967295 (in UINT32) cannot be used as indices.
    # https://github.com/KhronosGroup/glTF/issues/1142
    # https://github.com/KhronosGroup/glTF/pull/1476/files
    # Also, UINT8 mode is not supported:
    # https://github.com/KhronosGroup/glTF/issues/1471
    max_index = max(indices)
    if max_index < 65535:
        component_type = gltf2_io_constants.ComponentType.UnsignedShort
    elif max_index < 4294967295:
        component_type = gltf2_io_constants.ComponentType.UnsignedInt
    else:
        print_console('ERROR', 'A mesh contains too many vertices (' + str(max_index) + ') and needs to be split before export.')
        return None

    element_type = gltf2_io_constants.DataType.Scalar
    binary_data = gltf2_io_binary_data.BinaryData.from_list(indices, component_type)
    return gltf2_blender_gather_accessors.gather_accessor(
        binary_data,
        component_type,
        len(indices) // gltf2_io_constants.DataType.num_elements(element_type),
        None,
        None,
        element_type,
        export_settings
    )
def __gather_inverse_bind_matrices(blender_object, export_settings):
    bones = [group.name
             for group in blender_object.vertex_groups]  # get bones in skin
    modifiers = {m.type: m for m in blender_object.modifiers}
    armature = modifiers["ARMATURE"].object

    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)))

    if export_settings['gltf_def_bones'] is False:
        # build the hierarchy of nodes out of the bones
        root_bones = []
        for blender_bone in armature.pose.bones:
            if not blender_bone.parent:
                root_bones.append(blender_bone)
    else:
        _, children_, root_bones = get_bone_tree(None, armature)

    matrices = []

    # traverse the matrices in the same order as the joints and compute the inverse bind matrix
    def __collect_matrices(bone):
        if bone.name in bones:
            inverse_bind_matrix = (axis_basis_change @ (
                blender_object.matrix_world @ bone.bone.matrix_local)
                                   @ axis_basis_change.inverted()).inverted()
            matrices.append(inverse_bind_matrix)

        if export_settings['gltf_def_bones'] is False:
            for child in bone.children:
                __collect_matrices(child)
        else:
            if bone.name in children_.keys():
                for child in children_[bone.name]:
                    __collect_matrices(armature.pose.bones[child])

    # start with the "root" bones and recurse into children, in the same ordering as the how joints are gathered
    for root_bone in root_bones:
        __collect_matrices(root_bone)

    # flatten the matrices
    inverse_matrices = []
    for matrix in matrices:
        for column in range(0, 4):
            for row in range(0, 4):
                inverse_matrices.append(matrix[row][column])

    binary_data = gltf2_io_binary_data.BinaryData.from_list(
        inverse_matrices, gltf2_io_constants.ComponentType.Float)
    return gltf2_blender_gather_accessors.gather_accessor(
        binary_data, gltf2_io_constants.ComponentType.Float,
        len(inverse_matrices) // gltf2_io_constants.DataType.num_elements(
            gltf2_io_constants.DataType.Mat4), None, None,
        gltf2_io_constants.DataType.Mat4, 'accessorInverseBindMatrices',
        export_settings)
Пример #6
0
def __gather_input(channels: typing.Tuple[bpy.types.FCurve],
                   export_settings) -> gltf2_io.Accessor:
    """Gather the key time codes."""
    keyframes = gltf2_blender_gather_animation_sampler_keyframes.gather_keyframes(
        channels, export_settings)
    times = [k.seconds for k in keyframes]

    return gltf2_blender_gather_accessors.gather_accessor(
        gltf2_io_binary_data.BinaryData.from_list(
            times, gltf2_io_constants.ComponentType.Float),
        gltf2_io_constants.ComponentType.Float, len(times),
        tuple([max(times)]), tuple([min(times)]),
        gltf2_io_constants.DataType.Scalar, export_settings)
Пример #7
0
def __gather_inverse_bind_matrices(blender_object, mesh_object, export_settings):
    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)))

    # build the hierarchy of nodes out of the bones
    root_bones = []
    for blender_bone in blender_object.pose.bones:
        if not blender_bone.parent:
            root_bones.append(blender_bone)

    matrices = []

    # traverse the matrices in the same order as the joints and compute the inverse bind matrix
    def __collect_matrices(bone):
        matrix_world = gltf2_blender_math.multiply(blender_object.matrix_world, mesh_object.matrix_world.inverted())
        inverse_bind_matrix = gltf2_blender_math.multiply(
            axis_basis_change,
            gltf2_blender_math.multiply(
                matrix_world,
                bone.bone.matrix_local
            )
        ).inverted()
        matrices.append(inverse_bind_matrix)

        for child in bone.children:
            __collect_matrices(child)

    # start with the "root" bones and recurse into children, in the same ordering as the how joints are gathered
    for root_bone in root_bones:
        __collect_matrices(root_bone)

    # flatten the matrices
    inverse_matrices = []
    for matrix in matrices:
        for column in range(0, 4):
            for row in range(0, 4):
                inverse_matrices.append(matrix[row][column])

    binary_data = gltf2_io_binary_data.BinaryData.from_list(inverse_matrices, gltf2_io_constants.ComponentType.Float)
    return gltf2_blender_gather_accessors.gather_accessor(
        binary_data,
        gltf2_io_constants.ComponentType.Float,
        len(inverse_matrices) // gltf2_io_constants.DataType.num_elements(gltf2_io_constants.DataType.Mat4),
        None,
        None,
        gltf2_io_constants.DataType.Mat4,
        export_settings
    )
def __gather_input(channels: typing.Tuple[bpy.types.FCurve],
                   blender_object_if_armature: typing.Optional[bpy.types.Object],
                   export_settings
                   ) -> gltf2_io.Accessor:
    """Gather the key time codes."""
    keyframes = gltf2_blender_gather_animation_sampler_keyframes.gather_keyframes(blender_object_if_armature,
                                                                                  channels,
                                                                                  export_settings)
    times = [k.seconds for k in keyframes]

    return gltf2_blender_gather_accessors.gather_accessor(
        gltf2_io_binary_data.BinaryData.from_list(times, gltf2_io_constants.ComponentType.Float),
        gltf2_io_constants.ComponentType.Float,
        len(times),
        tuple([max(times)]),
        tuple([min(times)]),
        gltf2_io_constants.DataType.Scalar,
        export_settings
    )
def __gather_inverse_bind_matrices(armature_uuid, export_settings):

    blender_armature_object = export_settings['vtree'].nodes[
        armature_uuid].blender_object

    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)))

    # store matrix_world of armature in case we need to add a neutral bone
    export_settings['vtree'].nodes[
        armature_uuid].matrix_world_armature = blender_armature_object.matrix_world.copy(
        )

    bones_uuid = export_settings['vtree'].get_all_bones(armature_uuid)

    def __collect_matrices(bone):
        inverse_bind_matrix = (
            axis_basis_change @ (blender_armature_object.matrix_world
                                 @ bone.bone.matrix_local)).inverted_safe()
        matrices.append(inverse_bind_matrix)

    matrices = []
    for b in bones_uuid:
        __collect_matrices(blender_armature_object.pose.bones[
            export_settings['vtree'].nodes[b].blender_bone.name])

    # flatten the matrices
    inverse_matrices = []
    for matrix in matrices:
        for column in range(0, 4):
            for row in range(0, 4):
                inverse_matrices.append(matrix[row][column])

    binary_data = gltf2_io_binary_data.BinaryData.from_list(
        inverse_matrices, gltf2_io_constants.ComponentType.Float)
    return gltf2_blender_gather_accessors.gather_accessor(
        binary_data, gltf2_io_constants.ComponentType.Float,
        len(inverse_matrices) // gltf2_io_constants.DataType.num_elements(
            gltf2_io_constants.DataType.Mat4), None, None,
        gltf2_io_constants.DataType.Mat4, export_settings)
def __gather_inverse_bind_matrices(blender_object, mesh_object, export_settings):
    inverse_matrices = []

    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)))

    # # artificial torso, as needed by glTF
    # inverse_bind_matrix = blender_object.matrix_world.inverted() * axis_basis_change.inverted()
    # for column in range(0, 4):
    #     for row in range(0, 4):
    #         inverse_matrices.append(inverse_bind_matrix[row][column])

    #
    for blender_bone in blender_object.pose.bones:
        matrix_world = gltf2_blender_math.multiply(blender_object.matrix_world, mesh_object.matrix_world.inverted())
        inverse_bind_matrix = gltf2_blender_math.multiply(
            axis_basis_change,
            gltf2_blender_math.multiply(
                matrix_world,
                blender_bone.bone.matrix_local
            )
        ).inverted()

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

    binary_data = gltf2_io_binary_data.BinaryData.from_list(inverse_matrices, gltf2_io_constants.ComponentType.Float)
    return gltf2_blender_gather_accessors.gather_accessor(
        binary_data,
        gltf2_io_constants.ComponentType.Float,
        len(inverse_matrices) // gltf2_io_constants.DataType.num_elements(gltf2_io_constants.DataType.Mat4),
        None,
        None,
        gltf2_io_constants.DataType.Mat4,
        export_settings
    )
    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)