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) }
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': {} }
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': {} }
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) }
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
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