Example #1
0
def _import_vertices_mod156(mod, mesh):
    box_width = abs(mod.box_min_x) + abs(mod.box_max_x)
    box_height = abs(mod.box_min_y) + abs(mod.box_max_y)
    box_length = abs(mod.box_min_z) + abs(mod.box_max_z)

    vertices_array = get_vertices_array(mod, mesh)

    if mesh.vertex_format != 0:
        vertices = (transform_vertices_from_bbox(vf, box_width, box_height,
                                                 box_length)
                    for vf in vertices_array)
    else:
        vertices = ((vf.position_x, vf.position_y, vf.position_z)
                    for vf in vertices_array)
    vertices = (y_up_to_z_up(vertex_tuple) for vertex_tuple in vertices)
    vertices = ((x / 100, y / 100, z / 100) for x, y, z in vertices)

    # TODO: investigate why uvs don't appear above the image in the UV editor
    list_of_tuples = [(unpack_half_float(v.uv_x),
                       unpack_half_float(v.uv_y) * -1) for v in vertices_array]
    return {
        'locations': list(vertices),
        'uvs': list(chain.from_iterable(list_of_tuples)),
        'weights_per_bone': _get_weights_per_bone(mod, mesh, vertices_array)
    }
Example #2
0
def _import_vertices_mod210(mod, mesh):
    vertices_array = get_vertices_array(mod, mesh)
    vertices = ((vf.position_x / 32767, vf.position_y / 32767, vf.position_z / 32767)
                for vf in vertices_array)
    vertices = (y_up_to_z_up(vertex_tuple) for vertex_tuple in vertices)

    # TODO: investigate why uvs don't appear above the image in the UV editor
    list_of_tuples = [(unpack_half_float(v.uv_x), unpack_half_float(v.uv_y) * -1) for v in vertices_array]
    return {'locations': list(vertices),
            'uvs': list(chain.from_iterable(list_of_tuples)),
            'weights_per_bone': {}
            }
Example #3
0
def _import_vertices_mod210(mod, mesh):
    vertices_array = get_vertices_array(mod, mesh)
    vertices = ((vf.position_x / 32767, vf.position_y / 32767,
                 vf.position_z / 32767) for vf in vertices_array)
    vertices = (y_up_to_z_up(vertex_tuple) for vertex_tuple in vertices)

    # TODO: investigate why uvs don't appear above the image in the UV editor
    list_of_tuples = [(unpack_half_float(v.uv_x),
                       unpack_half_float(v.uv_y) * -1) for v in vertices_array]
    return {
        'locations': list(vertices),
        'uvs': list(chain.from_iterable(list_of_tuples)),
        'weights_per_bone': {}
    }
Example #4
0
def _import_vertices_mod156(mod, mesh):
    box_width = abs(mod.box_min_x) + abs(mod.box_max_x)
    box_height = abs(mod.box_min_y) + abs(mod.box_max_y)
    box_length = abs(mod.box_min_z) + abs(mod.box_max_z)

    vertices_array = get_vertices_array(mod, mesh)

    if mesh.vertex_format != 0:
        vertices = (transform_vertices_from_bbox(vf, box_width, box_height, box_length)
                    for vf in vertices_array)
    else:
        vertices = ((vf.position_x, vf.position_y, vf.position_z) for vf in vertices_array)
    vertices = (y_up_to_z_up(vertex_tuple) for vertex_tuple in vertices)
    vertices = ((x / 100, y / 100, z / 100) for x, y, z in vertices)

    # TODO: investigate why uvs don't appear above the image in the UV editor
    list_of_tuples = [(unpack_half_float(v.uv_x), unpack_half_float(v.uv_y) * -1) for v in vertices_array]
    return {'locations': list(vertices),
            'uvs': list(chain.from_iterable(list_of_tuples)),
            'weights_per_bone': _get_weights_per_bone(mod, mesh, vertices_array)
            }
Example #5
0
def _export_vertices(blender_mesh_object, bounding_box, saved_mod, mesh_index):
    saved_mesh = saved_mod.meshes_array[mesh_index]
    if saved_mod.bone_palette_array:
        bone_palette = saved_mod.bone_palette_array[
            saved_mesh.bone_palette_index].values[:]
    else:
        bone_palette = []
    blender_mesh = blender_mesh_object.data
    vertex_count = len(blender_mesh.vertices)
    weights_per_vertex = get_bone_indices_and_weights_per_vertex(
        blender_mesh_object)
    # TODO: check the number of uv layers
    uvs_per_vertex = get_uvs_per_vertex(blender_mesh_object.data,
                                        blender_mesh_object.data.uv_layers[0])

    VF = VERTEX_FORMATS_TO_CLASSES[saved_mesh.vertex_format]
    '''
    # Unfortunately this fails in some cases and could crash the game; until some mesh unknowns are figured out,
    # relying on saved_mesh data
    # e.g. pl0000.mod from uPl00ChrisNormal.arc, meshes_array[30] has max bones per vertex = 4, but the
    # original file has 5
    if weights_per_vertex:
        max_bones_per_vertex = max({len(data) for data in weights_per_vertex.values()})
        if max_bones_per_vertex > 8:
            raise RuntimeError("The mesh '{}' contains some vertex that are weighted by "
                               "more than 8 bones, which is not supported. Fix it and try again"
                               .format(blender_mesh.name))
        VF = VERTEX_FORMATS_TO_CLASSES[max_bones_per_vertex]
    '''

    for vertex_index, (uv_x, uv_y) in uvs_per_vertex.items():
        # flipping for dds textures
        uv_y *= -1
        uv_x = pack_half_float(uv_x)
        uv_y = pack_half_float(uv_y)
        uvs_per_vertex[vertex_index] = (uv_x, uv_y)

    if uvs_per_vertex and len(uvs_per_vertex) != vertex_count:
        # TODO: logging
        print('There are some vertices with no uvs in mesh in {}.'
              'Vertex count: {} UVs per vertex: {}'.format(
                  blender_mesh.name, vertex_count, len(uvs_per_vertex)))

    box_width = abs(bounding_box.min_x * 100) + abs(bounding_box.max_x * 100)
    box_height = abs(bounding_box.min_y * 100) + abs(bounding_box.max_y * 100)
    box_length = abs(bounding_box.min_z * 100) + abs(bounding_box.max_z * 100)

    vertices_array = (VF * vertex_count)()
    has_bones = hasattr(VF, 'bone_indices')
    has_tangents = hasattr(VF, 'tangent_x')
    has_second_uv_layer = hasattr(VF, 'uv2_x')
    original_vertices_array = get_vertices_array(
        saved_mod, saved_mod.meshes_array[mesh_index])
    for vertex_index, vertex in enumerate(blender_mesh.vertices):
        vertex_struct = vertices_array[vertex_index]
        original_vertex_struct = original_vertices_array[vertex_index]
        if weights_per_vertex:
            weights_data = weights_per_vertex[
                vertex_index]  # list of (bone_index, value)
            bone_indices = [
                bone_palette.index(bone_index)
                for bone_index, _ in weights_data
            ]
            weight_values = [
                round(weight_value * 255) for _, weight_value in weights_data
            ]
        else:
            bone_indices = []
            weight_values = []

        xyz = (vertex.co[0] * 100, vertex.co[1] * 100, vertex.co[2] * 100)
        xyz = z_up_to_y_up(xyz)
        if has_bones:
            # applying bounding box constraints
            xyz = vertices_export_locations(xyz, box_width, box_length,
                                            box_height)
        vertex_struct.position_x = xyz[0]
        vertex_struct.position_y = xyz[1]
        vertex_struct.position_z = xyz[2]
        vertex_struct.position_w = 32767
        if has_bones:
            array_size = ctypes.sizeof(vertex_struct.bone_indices)
            vertex_struct.bone_indices = (ctypes.c_ubyte *
                                          array_size)(*bone_indices)
            vertex_struct.weight_values = (ctypes.c_ubyte *
                                           array_size)(*weight_values)
        '''
        vertex_struct.normal_x = round(vertex.normal[0] * 127)
        vertex_struct.normal_y = round(vertex.normal[2] * 127) * -1
        vertex_struct.normal_z = round(vertex.normal[1] * 127)
        vertex_struct.normal_w = -1
        '''
        # XXX quick hack until normals can be exported ok in blender (gotta check fbx export or ask Bastien Montagne)
        vertex_struct.normal_x = original_vertex_struct.normal_x
        vertex_struct.normal_y = original_vertex_struct.normal_y
        vertex_struct.normal_z = original_vertex_struct.normal_z
        vertex_struct.normal_w = original_vertex_struct.normal_w
        if has_tangents:
            vertex_struct.tangent_x = original_vertex_struct.tangent_x
            vertex_struct.tangent_y = original_vertex_struct.tangent_x
            vertex_struct.tangent_z = original_vertex_struct.tangent_x
            vertex_struct.tangent_w = original_vertex_struct.tangent_x
            '''
            vertex_struct.tangent_x = -1
            vertex_struct.tangent_y = -1
            vertex_struct.tangent_z = -1
            vertex_struct.tangent_w = -1
            '''
        vertex_struct.uv_x = uvs_per_vertex.get(
            vertex_index, (0, 0))[0] if uvs_per_vertex else 0
        vertex_struct.uv_y = uvs_per_vertex.get(
            vertex_index, (0, 0))[1] if uvs_per_vertex else 0
        if has_second_uv_layer:
            vertex_struct.uv2_x = 0
            vertex_struct.uv2_y = 0
    return VF, vertices_array
Example #6
0
def _export_vertices(blender_mesh_object, bounding_box, saved_mod, mesh_index):
    saved_mesh = saved_mod.meshes_array[mesh_index]
    if saved_mod.bone_palette_array:
        bone_palette = saved_mod.bone_palette_array[saved_mesh.bone_palette_index].values[:]
    else:
        bone_palette = []
    blender_mesh = blender_mesh_object.data
    vertex_count = len(blender_mesh.vertices)
    weights_per_vertex = get_bone_indices_and_weights_per_vertex(blender_mesh_object)
    # TODO: check the number of uv layers
    uvs_per_vertex = get_uvs_per_vertex(blender_mesh_object.data, blender_mesh_object.data.uv_layers[0])

    VF = VERTEX_FORMATS_TO_CLASSES[saved_mesh.vertex_format]

    '''
    # Unfortunately this fails in some cases and could crash the game; until some mesh unknowns are figured out,
    # relying on saved_mesh data
    # e.g. pl0000.mod from uPl00ChrisNormal.arc, meshes_array[30] has max bones per vertex = 4, but the
    # original file has 5
    if weights_per_vertex:
        max_bones_per_vertex = max({len(data) for data in weights_per_vertex.values()})
        if max_bones_per_vertex > 8:
            raise RuntimeError("The mesh '{}' contains some vertex that are weighted by "
                               "more than 8 bones, which is not supported. Fix it and try again"
                               .format(blender_mesh.name))
        VF = VERTEX_FORMATS_TO_CLASSES[max_bones_per_vertex]
    '''

    for vertex_index, (uv_x, uv_y) in uvs_per_vertex.items():
        # flipping for dds textures
        uv_y *= -1
        uv_x = pack_half_float(uv_x)
        uv_y = pack_half_float(uv_y)
        uvs_per_vertex[vertex_index] = (uv_x, uv_y)

    if uvs_per_vertex and len(uvs_per_vertex) != vertex_count:
        # TODO: logging
        print('There are some vertices with no uvs in mesh in {}.'
              'Vertex count: {} UVs per vertex: {}'.format(blender_mesh.name, vertex_count,
                                                           len(uvs_per_vertex)))

    box_width = abs(bounding_box.min_x * 100) + abs(bounding_box.max_x * 100)
    box_height = abs(bounding_box.min_y * 100) + abs(bounding_box.max_y * 100)
    box_length = abs(bounding_box.min_z * 100) + abs(bounding_box.max_z * 100)

    vertices_array = (VF * vertex_count)()
    has_bones = hasattr(VF, 'bone_indices')
    has_tangents = hasattr(VF, 'tangent_x')
    has_second_uv_layer = hasattr(VF, 'uv2_x')
    original_vertices_array = get_vertices_array(saved_mod, saved_mod.meshes_array[mesh_index])
    for vertex_index, vertex in enumerate(blender_mesh.vertices):
        vertex_struct = vertices_array[vertex_index]
        original_vertex_struct = original_vertices_array[vertex_index]
        if weights_per_vertex:
            weights_data = weights_per_vertex[vertex_index]   # list of (bone_index, value)
            bone_indices = [bone_palette.index(bone_index) for bone_index, _ in weights_data]
            weight_values = [round(weight_value * 255) for _, weight_value in weights_data]
        else:
            bone_indices = []
            weight_values = []

        xyz = (vertex.co[0] * 100, vertex.co[1] * 100, vertex.co[2] * 100)
        xyz = z_up_to_y_up(xyz)
        if has_bones:
            # applying bounding box constraints
            xyz = vertices_export_locations(xyz, box_width, box_length, box_height)
        vertex_struct.position_x = xyz[0]
        vertex_struct.position_y = xyz[1]
        vertex_struct.position_z = xyz[2]
        vertex_struct.position_w = 32767
        if has_bones:
            array_size = ctypes.sizeof(vertex_struct.bone_indices)
            vertex_struct.bone_indices = (ctypes.c_ubyte * array_size)(*bone_indices)
            vertex_struct.weight_values = (ctypes.c_ubyte * array_size)(*weight_values)
        '''
        vertex_struct.normal_x = round(vertex.normal[0] * 127)
        vertex_struct.normal_y = round(vertex.normal[2] * 127) * -1
        vertex_struct.normal_z = round(vertex.normal[1] * 127)
        vertex_struct.normal_w = -1
        '''
        # XXX quick hack until normals can be exported ok in blender (gotta check fbx export or ask Bastien Montagne)
        vertex_struct.normal_x = original_vertex_struct.normal_x
        vertex_struct.normal_y = original_vertex_struct.normal_y
        vertex_struct.normal_z = original_vertex_struct.normal_z
        vertex_struct.normal_w = original_vertex_struct.normal_w
        if has_tangents:
            vertex_struct.tangent_x = original_vertex_struct.tangent_x
            vertex_struct.tangent_y = original_vertex_struct.tangent_x
            vertex_struct.tangent_z = original_vertex_struct.tangent_x
            vertex_struct.tangent_w = original_vertex_struct.tangent_x
            '''
            vertex_struct.tangent_x = -1
            vertex_struct.tangent_y = -1
            vertex_struct.tangent_z = -1
            vertex_struct.tangent_w = -1
            '''
        vertex_struct.uv_x = uvs_per_vertex.get(vertex_index, (0, 0))[0] if uvs_per_vertex else 0
        vertex_struct.uv_y = uvs_per_vertex.get(vertex_index, (0, 0))[1] if uvs_per_vertex else 0
        if has_second_uv_layer:
            vertex_struct.uv2_x = 0
            vertex_struct.uv2_y = 0
    return VF, vertices_array