コード例 #1
0
ファイル: blender_export.py プロジェクト: Brachi/albam
def _export_textures_and_materials(blender_objects, saved_mod):
    textures = get_textures_from_blender_objects(blender_objects)
    blender_materials = get_materials_from_blender_objects(blender_objects)
    textures_array = ((ctypes.c_char * 64) * len(textures))()
    materials_data_array = (MaterialData * len(blender_materials))()

    for i, texture in enumerate(textures):
        file_name = os.path.basename(texture.image.filepath)
        try:
            file_path = ntpath.join(texture.albam_imported_texture_folder, file_name)
        except AttributeError:
            raise ExportError('Texture {0} was not imported from an Arc file'.format(texture.name))
        try:
            file_path, _ = ntpath.splitext(file_path)
            textures_array[i] = (ctypes.c_char * 64)(*file_path.encode('ascii'))
        except UnicodeEncodeError:
            raise ExportError('Texture path {} is not in ascii'.format(file_path))
        if len(file_path) > 64:
            # TODO: what if relative path are used?
            raise ExportError('File path to texture {} is longer than 64 characters'
                              .format(file_path))

    for i, mat in enumerate(blender_materials):
        material_data = MaterialData()
        try:
            # TODO: Should use data from actual blender material
            saved_mat = saved_mod.materials_data_array[i]
        except IndexError:
            raise ExportError('Exporting models with more materials than the original not supported yet')
        material_data.unk_01 = saved_mat.unk_01
        material_data.unk_02 = saved_mat.unk_02
        material_data.unk_03 = saved_mat.unk_03
        material_data.unk_04 = saved_mat.unk_04
        material_data.unk_05 = saved_mat.unk_05
        material_data.unk_06 = saved_mat.unk_06
        material_data.unk_07 = saved_mat.unk_07
        for texture_slot in mat.texture_slots:
            if not texture_slot:
                continue
            texture = texture_slot.texture
            if not texture:
                # ?
                continue
            # texture_indices expects index-1 based
            try:
                texture_index = textures.index(texture) + 1
            except ValueError:
                # TODO: logging
                print('error in textures')
            material_data.texture_indices[texture.albam_imported_texture_type] = texture_index
        materials_data_array[i] = material_data

    return textures_array, materials_data_array
コード例 #2
0
def _export_textures_and_materials(blender_objects, saved_mod):
    textures = get_textures_from_blender_objects(blender_objects)
    blender_materials = get_materials_from_blender_objects(blender_objects)
    textures_array = ((ctypes.c_char * 64) * len(textures))()
    materials_data_array = (MaterialData * len(blender_materials))()

    for i, texture in enumerate(textures):
        file_name = os.path.basename(texture.image.filepath)
        try:
            file_path = ntpath.join(texture.albam_imported_texture_folder,
                                    file_name)
        except AttributeError:
            raise ExportError(
                'Texture {0} was not imported from an Arc file'.format(
                    texture.name))
        try:
            file_path, _ = ntpath.splitext(file_path)
            textures_array[i] = (ctypes.c_char *
                                 64)(*file_path.encode('ascii'))
        except UnicodeEncodeError:
            raise ExportError(
                'Texture path {} is not in ascii'.format(file_path))
        if len(file_path) > 64:
            # TODO: what if relative path are used?
            raise ExportError(
                'File path to texture {} is longer than 64 characters'.format(
                    file_path))

    for i, mat in enumerate(blender_materials):
        material_data = MaterialData()
        try:
            # TODO: Should use data from actual blender material
            saved_mat = saved_mod.materials_data_array[i]
        except IndexError:
            raise ExportError(
                'Exporting models with more materials than the original not supported yet'
            )
        material_data.unk_01 = saved_mat.unk_01
        material_data.unk_02 = saved_mat.unk_02
        material_data.unk_03 = saved_mat.unk_03
        material_data.unk_04 = saved_mat.unk_04
        material_data.unk_05 = saved_mat.unk_05
        material_data.unk_06 = saved_mat.unk_06
        material_data.unk_07 = saved_mat.unk_07
        for texture_slot in mat.texture_slots:
            if not texture_slot:
                continue
            texture = texture_slot.texture
            if not texture:
                # ?
                continue
            # texture_indices expects index-1 based
            try:
                texture_index = textures.index(texture) + 1
            except ValueError:
                # TODO: logging
                print('error in textures')
            material_data.texture_indices[
                texture.albam_imported_texture_type] = texture_index
        materials_data_array[i] = material_data

    return textures_array, materials_data_array
コード例 #3
0
def export_mod156(parent_blender_object):
    '''The blender_object provided should have meshes as children'''
    try:
        saved_mod = Mod156(
            file_path=BytesIO(parent_blender_object.albam_imported_item.data))
    except AttributeError:
        raise ExportError(
            "Can't export '{0}' to Mod156, the model to be exported "
            "wasn't imported using Albam".format(parent_blender_object.name))

    children_objects = [child for child in parent_blender_object.children]
    empty_children = [c for c in children_objects if c.type == 'EMPTY']
    meshes_children = [c for c in children_objects if c.type == 'MESH']
    bounding_box = get_bounding_box_positions_from_blender_objects(
        children_objects)

    if len(meshes_children) < len(saved_mod.meshes_array) and empty_children:
        # There were failed meshes that were replaced as empties in the import
        # We need to remove the extra weight groups (or whaterver they are),
        # before exporting
        failed_indices = {
            i
            for i, obj in enumerate(parent_blender_object.children)
            if obj.type == 'EMPTY'
        }
        new_bytes = []
        current_position = 0
        for i, mesh in enumerate(saved_mod.meshes_array):
            size = 144 * mesh.vertex_group_count
            data = saved_mod.meshes_array_2[current_position:current_position +
                                            size]
            current_position = current_position + size
            if i in failed_indices:
                continue
            else:
                new_bytes.extend(data)
        # the misterious extra 4 bytes for mod.156
        new_bytes.extend(saved_mod.meshes_array_2[-4:])
        meshes_array_2 = (ctypes.c_ubyte * len(new_bytes))(*new_bytes)
    elif len(meshes_children) != len(
            saved_mod.meshes_array) and not empty_children:
        raise ExportError(
            "Can't import {0}, different meshes quantity ({1} vs {2}) "
            "Support for this will come soon".format(
                parent_blender_object.name, len(saved_mod.meshes_array),
                len(children_objects)))
    else:
        meshes_array_2 = saved_mod.meshes_array_2

    textures_array, materials_array = _export_textures_and_materials(
        children_objects, saved_mod)
    meshes_array, vertex_buffer, index_buffer = _export_meshes(
        children_objects, bounding_box, saved_mod)

    bone_count = get_bone_count_from_blender_objects([parent_blender_object])
    if not bone_count:
        bones_array_offset = 0
    elif bone_count and saved_mod.unk_08:
        bones_array_offset = 176 + len(saved_mod.unk_12)
    else:
        bones_array_offset = 176

    mod = Mod156(
        id_magic=b'MOD',
        version=156,
        version_rev=1,
        bone_count=bone_count,
        mesh_count=get_mesh_count_from_blender_objects(children_objects),
        material_count=len(materials_array),
        vertex_count=get_vertex_count_from_blender_objects(children_objects),
        face_count=(ctypes.sizeof(index_buffer) // 2) + 1,
        edge_count=0,  # TODO: add edge_count
        vertex_buffer_size=ctypes.sizeof(vertex_buffer),
        vertex_buffer_2_size=len(saved_mod.vertex_buffer_2),
        texture_count=len(textures_array),
        group_count=saved_mod.group_count,
        bones_array_offset=bones_array_offset,
        group_data_array=saved_mod.group_data_array,
        bone_palette_count=saved_mod.bone_palette_count,
        sphere_x=saved_mod.sphere_x,
        sphere_y=saved_mod.sphere_y,
        sphere_z=saved_mod.sphere_z,
        sphere_w=saved_mod.sphere_w,
        box_min_x=saved_mod.box_min_x,
        box_min_y=saved_mod.box_min_y,
        box_min_z=saved_mod.box_min_z,
        box_min_w=saved_mod.box_min_w,
        box_max_x=saved_mod.box_max_x,
        box_max_y=saved_mod.box_max_y,
        box_max_z=saved_mod.box_max_z,
        box_max_w=saved_mod.box_max_w,
        unk_01=saved_mod.unk_01,
        unk_02=saved_mod.unk_02,
        unk_03=saved_mod.unk_03,
        unk_04=saved_mod.unk_04,
        unk_05=saved_mod.unk_05,
        unk_06=saved_mod.unk_06,
        unk_07=saved_mod.unk_07,
        unk_08=saved_mod.unk_08,
        unk_09=saved_mod.unk_09,
        unk_10=saved_mod.unk_10,
        unk_11=saved_mod.unk_11,
        unk_12=saved_mod.unk_12,
        bones_array=saved_mod.bones_array,
        bones_unk_matrix_array=saved_mod.bones_unk_matrix_array,
        bones_world_transform_matrix_array=saved_mod.
        bones_world_transform_matrix_array,
        unk_13=saved_mod.unk_13,
        bone_palette_array=saved_mod.bone_palette_array,
        textures_array=textures_array,
        materials_data_array=materials_array,
        meshes_array=meshes_array,
        meshes_array_2=meshes_array_2,
        vertex_buffer=vertex_buffer,
        vertex_buffer_2=saved_mod.vertex_buffer_2,
        index_buffer=index_buffer)
    mod.bones_array_offset = get_offset(mod,
                                        'bones_array') if mod.bone_count else 0
    mod.group_offset = get_offset(mod, 'group_data_array')
    mod.textures_array_offset = get_offset(mod, 'textures_array')
    mod.meshes_array_offset = get_offset(mod, 'meshes_array')
    mod.vertex_buffer_offset = get_offset(mod, 'vertex_buffer')
    mod.vertex_buffer_2_offset = get_offset(mod, 'vertex_buffer_2')
    mod.index_buffer_offset = get_offset(mod, 'index_buffer')
    return mod, get_textures_from_blender_objects(children_objects)
コード例 #4
0
ファイル: blender_export.py プロジェクト: Brachi/albam
def export_mod156(parent_blender_object):
    '''The blender_object provided should have meshes as children'''
    try:
        saved_mod = Mod156(file_path=BytesIO(parent_blender_object.albam_imported_item.data))
    except AttributeError:
        raise ExportError("Can't export '{0}' to Mod156, the model to be exported "
                          "wasn't imported using Albam"
                          .format(parent_blender_object.name))

    children_objects = [child for child in parent_blender_object.children]
    empty_children = [c for c in children_objects if c.type == 'EMPTY']
    meshes_children = [c for c in children_objects if c.type == 'MESH']
    bounding_box = get_bounding_box_positions_from_blender_objects(children_objects)

    if len(meshes_children) < len(saved_mod.meshes_array) and empty_children:
        # There were failed meshes that were replaced as empties in the import
        # We need to remove the extra weight groups (or whaterver they are),
        # before exporting
        failed_indices = {i for i, obj in enumerate(parent_blender_object.children)
                          if obj.type == 'EMPTY'}
        new_bytes = []
        current_position = 0
        for i, mesh in enumerate(saved_mod.meshes_array):
            size = 144 * mesh.vertex_group_count
            data = saved_mod.meshes_array_2[current_position:current_position + size]
            current_position = current_position + size
            if i in failed_indices:
                continue
            else:
                new_bytes.extend(data)
        # the misterious extra 4 bytes for mod.156
        new_bytes.extend(saved_mod.meshes_array_2[-4:])
        meshes_array_2 = (ctypes.c_ubyte * len(new_bytes))(*new_bytes)
    elif len(meshes_children) != len(saved_mod.meshes_array) and not empty_children:
        raise ExportError("Can't import {0}, different meshes quantity ({1} vs {2}) "
                          "Support for this will come soon".format(parent_blender_object.name,
                                                                   len(saved_mod.meshes_array),
                                                                   len(children_objects)))
    else:
        meshes_array_2 = saved_mod.meshes_array_2

    textures_array, materials_array = _export_textures_and_materials(children_objects, saved_mod)
    meshes_array, vertex_buffer, index_buffer = _export_meshes(children_objects, bounding_box, saved_mod)

    bone_count = get_bone_count_from_blender_objects([parent_blender_object])
    if not bone_count:
        bones_array_offset = 0
    elif bone_count and saved_mod.unk_08:
        bones_array_offset = 176 + len(saved_mod.unk_12)
    else:
        bones_array_offset = 176

    mod = Mod156(id_magic=b'MOD',
                 version=156,
                 version_rev=1,
                 bone_count=bone_count,
                 mesh_count=get_mesh_count_from_blender_objects(children_objects),
                 material_count=len(materials_array),
                 vertex_count=get_vertex_count_from_blender_objects(children_objects),
                 face_count=(ctypes.sizeof(index_buffer) // 2) + 1,
                 edge_count=0,  # TODO: add edge_count
                 vertex_buffer_size=ctypes.sizeof(vertex_buffer),
                 vertex_buffer_2_size=len(saved_mod.vertex_buffer_2),
                 texture_count=len(textures_array),
                 group_count=saved_mod.group_count,
                 bones_array_offset=bones_array_offset,
                 group_data_array=saved_mod.group_data_array,
                 bone_palette_count=saved_mod.bone_palette_count,
                 sphere_x=saved_mod.sphere_x,
                 sphere_y=saved_mod.sphere_y,
                 sphere_z=saved_mod.sphere_z,
                 sphere_w=saved_mod.sphere_w,
                 box_min_x=saved_mod.box_min_x,
                 box_min_y=saved_mod.box_min_y,
                 box_min_z=saved_mod.box_min_z,
                 box_min_w=saved_mod.box_min_w,
                 box_max_x=saved_mod.box_max_x,
                 box_max_y=saved_mod.box_max_y,
                 box_max_z=saved_mod.box_max_z,
                 box_max_w=saved_mod.box_max_w,
                 unk_01=saved_mod.unk_01,
                 unk_02=saved_mod.unk_02,
                 unk_03=saved_mod.unk_03,
                 unk_04=saved_mod.unk_04,
                 unk_05=saved_mod.unk_05,
                 unk_06=saved_mod.unk_06,
                 unk_07=saved_mod.unk_07,
                 unk_08=saved_mod.unk_08,
                 unk_09=saved_mod.unk_09,
                 unk_10=saved_mod.unk_10,
                 unk_11=saved_mod.unk_11,
                 unk_12=saved_mod.unk_12,
                 bones_array=saved_mod.bones_array,
                 bones_unk_matrix_array=saved_mod.bones_unk_matrix_array,
                 bones_world_transform_matrix_array=saved_mod.bones_world_transform_matrix_array,
                 unk_13=saved_mod.unk_13,
                 bone_palette_array=saved_mod.bone_palette_array,
                 textures_array=textures_array,
                 materials_data_array=materials_array,
                 meshes_array=meshes_array,
                 meshes_array_2=meshes_array_2,
                 vertex_buffer=vertex_buffer,
                 vertex_buffer_2=saved_mod.vertex_buffer_2,
                 index_buffer=index_buffer
                 )
    mod.bones_array_offset = get_offset(mod, 'bones_array') if mod.bone_count else 0
    mod.group_offset = get_offset(mod, 'group_data_array')
    mod.textures_array_offset = get_offset(mod, 'textures_array')
    mod.meshes_array_offset = get_offset(mod, 'meshes_array')
    mod.vertex_buffer_offset = get_offset(mod, 'vertex_buffer')
    mod.vertex_buffer_2_offset = get_offset(mod, 'vertex_buffer_2')
    mod.index_buffer_offset = get_offset(mod, 'index_buffer')
    return mod, get_textures_from_blender_objects(children_objects)