Compare commits

..

5 Commits
5.0.1 ... 5.0.3

Author SHA1 Message Date
Colin Basnett
741357d0af Incremented version to 5.0.3 2023-08-14 22:43:26 -07:00
Colin Basnett
fb2ab89766 Fixed a compatibility issue caused by the fix to #43 2023-08-14 22:42:59 -07:00
Colin Basnett
d0d6deb63c Changed name of faces that couldn't be added to "invalid" faces instead of "degenerate" faces
This is because a face can still be rejected by being a duplicate, but it doesn't necessarily have to be degenerate (i.e., a line or point).
2023-08-10 23:38:56 -07:00
Colin Basnett
e9b09dc651 Incremented version to 5.0.2 2023-08-09 21:03:49 -07:00
Colin Basnett
ed89e78927 Fix #43: Wedges can now address vertices with indices greater than 65535 2023-08-09 20:14:24 -07:00
5 changed files with 31 additions and 15 deletions

View File

@@ -1,7 +1,7 @@
bl_info = { bl_info = {
"name": "PSK/PSA Importer/Exporter", "name": "PSK/PSA Importer/Exporter",
"author": "Colin Basnett, Yurii Ti", "author": "Colin Basnett, Yurii Ti",
"version": (5, 0, 1), "version": (5, 0, 3),
"blender": (3, 4, 0), "blender": (3, 4, 0),
"description": "PSK/PSA Import/Export (.psk/.psa)", "description": "PSK/PSA Import/Export (.psk/.psa)",
"warning": "", "warning": "",

View File

@@ -8,10 +8,10 @@ from bpy.types import Context, Armature, Action, Object, AnimData, TimelineMarke
from bpy_extras.io_utils import ExportHelper from bpy_extras.io_utils import ExportHelper
from bpy_types import Operator from bpy_types import Operator
from io_scene_psk_psa.helpers import populate_bone_group_list, get_nla_strips_in_timeframe from ..builder import build_psa, PsaBuildSequence, PsaBuildOptions
from io_scene_psk_psa.psa.builder import build_psa, PsaBuildSequence, PsaBuildOptions from ..export.properties import PSA_PG_export, PSA_PG_export_action_list_item, filter_sequences
from io_scene_psk_psa.psa.export.properties import PSA_PG_export, PSA_PG_export_action_list_item, filter_sequences from ..writer import write_psa
from io_scene_psk_psa.psa.writer import write_psa from ...helpers import populate_bone_group_list, get_nla_strips_in_timeframe
def is_action_for_armature(armature: Armature, action: Action): def is_action_for_armature(armature: Armature, action: Action):

View File

@@ -16,8 +16,7 @@ class Psk(object):
class Wedge16(Structure): class Wedge16(Structure):
_fields_ = [ _fields_ = [
('point_index', c_uint16), ('point_index', c_uint32),
('padding1', c_int16),
('u', c_float), ('u', c_float),
('v', c_float), ('v', c_float),
('material_index', c_uint8), ('material_index', c_uint8),

View File

@@ -150,17 +150,22 @@ def import_psk(psk: Psk, context, options: PskImportOptions) -> PskImportResult:
bm.verts.ensure_lookup_table() bm.verts.ensure_lookup_table()
degenerate_face_indices = set() invalid_face_indices = set()
for face_index, face in enumerate(psk.faces): for face_index, face in enumerate(psk.faces):
point_indices = [bm.verts[psk.wedges[i].point_index] for i in reversed(face.wedge_indices)] point_indices = map(lambda i: psk.wedges[i].point_index, reversed(face.wedge_indices))
points = [bm.verts[i] for i in point_indices]
try: try:
bm_face = bm.faces.new(point_indices) bm_face = bm.faces.new(points)
bm_face.material_index = face.material_index bm_face.material_index = face.material_index
except ValueError: except ValueError:
degenerate_face_indices.add(face_index) # This happens for two reasons:
# 1. Two or more of the face's points are the same. (i.e, point indices of [0, 0, 1])
# 2. The face is a duplicate of another face. (i.e., point indices of [0, 1, 2] and [0, 1, 2])
invalid_face_indices.add(face_index)
if len(degenerate_face_indices) > 0: # TODO: Handle invalid faces better.
result.warnings.append(f'Discarded {len(degenerate_face_indices)} degenerate face(s).') if len(invalid_face_indices) > 0:
result.warnings.append(f'Discarded {len(invalid_face_indices)} invalid face(s).')
bm.to_mesh(mesh_data) bm.to_mesh(mesh_data)
@@ -168,7 +173,7 @@ def import_psk(psk: Psk, context, options: PskImportOptions) -> PskImportResult:
data_index = 0 data_index = 0
uv_layer = mesh_data.uv_layers.new(name='VTXW0000') uv_layer = mesh_data.uv_layers.new(name='VTXW0000')
for face_index, face in enumerate(psk.faces): for face_index, face in enumerate(psk.faces):
if face_index in degenerate_face_indices: if face_index in invalid_face_indices:
continue continue
face_wedges = [psk.wedges[i] for i in reversed(face.wedge_indices)] face_wedges = [psk.wedges[i] for i in reversed(face.wedge_indices)]
for wedge in face_wedges: for wedge in face_wedges:
@@ -183,7 +188,7 @@ def import_psk(psk: Psk, context, options: PskImportOptions) -> PskImportResult:
data_index = 0 data_index = 0
uv_layer = mesh_data.uv_layers.new(name=f'EXTRAUV{extra_uv_index}') uv_layer = mesh_data.uv_layers.new(name=f'EXTRAUV{extra_uv_index}')
for face_index, face in enumerate(psk.faces): for face_index, face in enumerate(psk.faces):
if face_index in degenerate_face_indices: if face_index in invalid_face_indices:
continue continue
for wedge_index in reversed(face.wedge_indices): for wedge_index in reversed(face.wedge_indices):
u, v = psk.extra_uvs[wedge_index_offset + wedge_index] u, v = psk.extra_uvs[wedge_index_offset + wedge_index]

View File

@@ -78,4 +78,16 @@ def read_psk(path: str) -> Psk:
''' '''
psk.material_references = _read_material_references(path) psk.material_references = _read_material_references(path)
'''
Tools like UEViewer and CUE4Parse write the point index as a 32-bit integer, exploiting the fact that due to struct
alignment, there were 16-bits of padding following the original 16-bit point index in the wedge struct.
However, this breaks compatibility with PSK files that were created with older tools that treated the
point index as a 16-bit integer and might have junk data written to the padding bits.
To work around this, we check if each point is still addressable using a 16-bit index, and if it is, assume the
point index is a 16-bit integer and truncate the high bits.
'''
if len(psk.points) <= 65536:
for wedge in psk.wedges:
wedge.point_index &= 0xFFFF
return psk return psk