From 65833b57e8c977f34c82bfdac35cebca0e889aa1 Mon Sep 17 00:00:00 2001 From: Colin Basnett Date: Tue, 7 Sep 2021 21:40:42 -0700 Subject: [PATCH] Fix for bug https://github.com/DarklightGames/io_export_psk_psa/issues/7 --- io_export_psk_psa/psa/builder.py | 4 +- io_export_psk_psa/psk/builder.py | 64 +++++++++++++++++-------------- io_export_psk_psa/psk/data.py | 24 ++++++++---- io_export_psk_psa/psk/exporter.py | 11 +++++- 4 files changed, 62 insertions(+), 41 deletions(-) diff --git a/io_export_psk_psa/psa/builder.py b/io_export_psk_psa/psa/builder.py index e1846f9..de24c00 100644 --- a/io_export_psk_psa/psa/builder.py +++ b/io_export_psk_psa/psa/builder.py @@ -70,8 +70,6 @@ class PsaBuilder(object): psa.bones.append(psa_bone) - frame_start_index = 0 - for action in options.actions: if len(action.fcurves) == 0: continue @@ -84,7 +82,7 @@ class PsaBuilder(object): sequence = Psa.Sequence() sequence.name = bytes(action.name, encoding='utf-8') sequence.frame_count = frame_max - frame_min + 1 - sequence.frame_start_index = frame_start_index + sequence.frame_start_index = 0 sequence.fps = context.scene.render.fps frame_count = frame_max - frame_min + 1 diff --git a/io_export_psk_psa/psk/builder.py b/io_export_psk_psa/psk/builder.py index 88790a7..2cc82fb 100644 --- a/io_export_psk_psa/psk/builder.py +++ b/io_export_psk_psa/psk/builder.py @@ -10,6 +10,7 @@ class PskInputObjects(object): self.mesh_objects = [] self.armature_object = None + class PskBuilder(object): def __init__(self): pass @@ -52,14 +53,8 @@ class PskBuilder(object): def build(self, context) -> Psk: input_objects = PskBuilder.get_input_objects(context) - wedge_count = sum([len(m.data.loops) for m in input_objects.mesh_objects]) - if wedge_count <= 65536: - wedge_type = Psk.Wedge16 - else: - wedge_type = Psk.Wedge32 psk = Psk() - materials = OrderedDict() if input_objects.armature_object is None: @@ -111,10 +106,7 @@ class PskBuilder(object): psk.bones.append(psk_bone) vertex_offset = 0 - wedge_offset = 0 - weight_offset = 0 - # TODO: if there is an edge-split modifier, we need to apply it (maybe?) for object in input_objects.mesh_objects: # VERTICES for vertex in object.data.vertices: @@ -125,17 +117,7 @@ class PskBuilder(object): point.z = v.z psk.points.append(point) - # WEDGES uv_layer = object.data.uv_layers.active.data - psk.wedges.extend([wedge_type() for _ in range(len(object.data.loops))]) - - for loop_index, loop in enumerate(object.data.loops): - wedge = psk.wedges[wedge_offset + loop_index] - wedge.material_index = 0 # NOTE: this material index is set properly while building the faces - wedge.point_index = loop.vertex_index + vertex_offset - wedge.u, wedge.v = uv_layer[loop_index].uv - wedge.v = 1.0 - wedge.v - psk.wedges.append(wedge) # MATERIALS material_indices = [] @@ -153,20 +135,46 @@ class PskBuilder(object): material_index = material.texture_index material_indices.append(material_index) - # FACES + # WEDGES object.data.calc_loop_triangles() + + # Build a list of non-unique wedges. + wedges = [] + for loop_index, loop in enumerate(object.data.loops): + wedge = Psk.Wedge() + wedge.point_index = loop.vertex_index + vertex_offset + wedge.u, wedge.v = uv_layer[loop_index].uv + wedge.v = 1.0 - wedge.v + wedges.append(wedge) + + # Assign material indices to the wedges. + for triangle in object.data.loop_triangles: + for loop_index in triangle.loops: + wedges[loop_index].material_index = material_indices[triangle.material_index] + + # Populate the list of wedges with unique wedges & build a look-up table of loop indices to wedge indices + wedge_indices = {} + loop_wedge_indices = [-1] * len(object.data.loops) + for loop_index, wedge in enumerate(wedges): + wedge_hash = hash(wedge) + if wedge_hash in wedge_indices: + loop_wedge_indices[loop_index] = wedge_indices[wedge_hash] + else: + wedge_index = len(psk.wedges) + wedge_indices[wedge_hash] = wedge_index + psk.wedges.append(wedge) + loop_wedge_indices[loop_index] = wedge_index + + # FACES poly_groups, groups = object.data.calc_smooth_groups(use_bitflags=True) for f in object.data.loop_triangles: face = Psk.Face() face.material_index = material_indices[f.material_index] - face.wedge_index_1 = f.loops[2] + wedge_offset - face.wedge_index_2 = f.loops[1] + wedge_offset - face.wedge_index_3 = f.loops[0] + wedge_offset + face.wedge_indices[0] = loop_wedge_indices[f.loops[2]] + face.wedge_indices[1] = loop_wedge_indices[f.loops[1]] + face.wedge_indices[2] = loop_wedge_indices[f.loops[0]] face.smoothing_groups = poly_groups[f.polygon_index] psk.faces.append(face) - # update the material index of the wedges - for i in range(3): - psk.wedges[wedge_offset + f.loops[i]].material_index = face.material_index # WEIGHTS # TODO: bone ~> vg might not be 1:1, provide a nice error message if this is the case @@ -190,8 +198,6 @@ class PskBuilder(object): w.weight = weight psk.weights.append(w) - vertex_offset += len(psk.points) - wedge_offset += len(psk.wedges) - weight_offset += len(psk.weights) + vertex_offset = len(psk.points) return psk diff --git a/io_export_psk_psa/psk/data.py b/io_export_psk_psa/psk/data.py index cf8d545..bfdc82f 100644 --- a/io_export_psk_psa/psk/data.py +++ b/io_export_psk_psa/psk/data.py @@ -4,30 +4,38 @@ from ..data import * class Psk(object): + class Wedge(object): + def __init__(self): + self.point_index: int = 0 + self.u: float = 0.0 + self.v: float = 0.0 + self.material_index: int = 0 + + def __hash__(self): + return hash(f'{self.point_index}-{self.u}-{self.v}-{self.material_index}') + class Wedge16(Structure): _fields_ = [ - ('point_index', c_int16), + ('point_index', c_uint16), ('padding1', c_int16), ('u', c_float), ('v', c_float), - ('material_index', c_int8), + ('material_index', c_uint8), ('reserved', c_int8), ('padding2', c_int16) ] class Wedge32(Structure): _fields_ = [ - ('point_index', c_int32), + ('point_index', c_uint32), ('u', c_float), ('v', c_float), - ('material_index', c_int32) + ('material_index', c_uint32) ] class Face(Structure): _fields_ = [ - ('wedge_index_1', c_int16), - ('wedge_index_2', c_int16), - ('wedge_index_3', c_int16), + ('wedge_indices', c_uint16 * 3), ('material_index', c_int8), ('aux_material_index', c_int8), ('smoothing_groups', c_int32) @@ -65,7 +73,7 @@ class Psk(object): def __init__(self): self.points: List[Vector3] = [] - self.wedges: List[Psk.Wedge16] = [] + self.wedges: List[Psk.Wedge] = [] self.faces: List[Psk.Face] = [] self.materials: List[Psk.Material] = [] self.weights: List[Psk.Weight] = [] diff --git a/io_export_psk_psa/psk/exporter.py b/io_export_psk_psa/psk/exporter.py index 55b7a35..fa45eec 100644 --- a/io_export_psk_psa/psk/exporter.py +++ b/io_export_psk_psa/psk/exporter.py @@ -29,7 +29,16 @@ class PskExporter(object): else: wedge_type = Psk.Wedge32 - self.write_section(fp, b'VTXW0000', wedge_type, self.psk.wedges) + wedges = [] + for index, w in enumerate(self.psk.wedges): + wedge = wedge_type() + wedge.material_index = w.material_index + wedge.u = w.u + wedge.v = w.v + wedge.point_index = w.point_index + wedges.append(wedge) + + self.write_section(fp, b'VTXW0000', wedge_type, wedges) self.write_section(fp, b'FACE0000', Psk.Face, self.psk.faces) self.write_section(fp, b'MATT0000', Psk.Material, self.psk.materials) self.write_section(fp, b'REFSKELT', Psk.Bone, self.psk.bones)