diff --git a/io_scene_psk_psa/psk/data.py b/io_scene_psk_psa/psk/data.py index cb87058..aa93de5 100644 --- a/io_scene_psk_psa/psk/data.py +++ b/io_scene_psk_psa/psk/data.py @@ -80,6 +80,19 @@ class Psk(object): ('bone_index', c_int32), ] + class MorphInfo(Structure): + _fields_ = [ + ('name', c_char * 64), + ('vertex_count', c_int32) + ] + + class MorphData(Structure): + _fields_ = [ + ('position_delta', Vector3), + ('tangent_z_delta', Vector3), + ('point_index', c_int32) + ] + @property def has_extra_uvs(self): return len(self.extra_uvs) > 0 @@ -92,6 +105,10 @@ class Psk(object): def has_vertex_normals(self): return len(self.vertex_normals) > 0 + @property + def has_morph_data(self): + return len(self.morph_infos) > 0 + def __init__(self): self.points: List[Vector3] = [] self.wedges: List[Psk.Wedge] = [] @@ -102,3 +119,5 @@ class Psk(object): self.extra_uvs: List[Vector2] = [] self.vertex_colors: List[Color] = [] self.vertex_normals: List[Vector3] = [] + self.morph_infos: List[Psk.MorphInfo] = [] + self.morph_data: List[Psk.MorphData] = [] diff --git a/io_scene_psk_psa/psk/importer.py b/io_scene_psk_psa/psk/importer.py index e8f8aa5..e269c20 100644 --- a/io_scene_psk_psa/psk/importer.py +++ b/io_scene_psk_psa/psk/importer.py @@ -221,6 +221,7 @@ def import_psk(psk: Psk, context, options: PskImportOptions) -> PskImportResult: bm.normal_update() bm.free() + # WEIGHTS # Get a list of all bones that have weights associated with them. vertex_group_bone_indices = set(map(lambda weight: weight.bone_index, psk.weights)) vertex_groups: List[Optional[VertexGroup]] = [None] * len(psk.bones) @@ -230,6 +231,16 @@ def import_psk(psk: Psk, context, options: PskImportOptions) -> PskImportResult: for weight in psk.weights: vertex_groups[weight.bone_index].add((weight.point_index,), weight.weight, 'ADD') + # MORPHS (SHAPE KEYS) + morph_data_iterator = iter(psk.morph_data) + for morph_info in psk.morph_infos: + shape_key = mesh_object.shape_key_add(name=morph_info.name.decode('windows-1252'), from_mix=False) + + for _ in range(morph_info.vertex_count): + morph_data = next(morph_data_iterator) + x, y, z = morph_data.position_delta + shape_key.data[morph_data.point_index].co += Vector((x, -y, z)) + context.scene.collection.objects.link(mesh_object) # Add armature modifier to our mesh object. diff --git a/io_scene_psk_psa/psk/reader.py b/io_scene_psk_psa/psk/reader.py index f215f4f..f49c916 100644 --- a/io_scene_psk_psa/psk/reader.py +++ b/io_scene_psk_psa/psk/reader.py @@ -46,6 +46,10 @@ def read_psk(path: str) -> Psk: _read_types(fp, Vector2, section, psk.extra_uvs) elif section.name == b'VTXNORMS': _read_types(fp, Vector3, section, psk.vertex_normals) + elif section.name == b'MRPHINFO': + _read_types(fp, Psk.MorphInfo, section, psk.morph_infos) + elif section.name == b'MRPHDATA': + _read_types(fp, Psk.MorphData, section, psk.morph_data) else: # Section is not handled, skip it. fp.seek(section.data_size * section.data_count, os.SEEK_CUR)