Improved performance of PSK importer by ~40% for large meshes

This commit is contained in:
Colin Basnett
2025-05-18 01:16:20 -07:00
parent 00d9e3996c
commit 29831d7f09
3 changed files with 30 additions and 20 deletions

View File

@@ -163,8 +163,11 @@ def import_psk(psk: Psk, context: Context, name: str, options: PskImportOptions)
# Faces # Faces
invalid_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 = map(lambda i: psk.wedges[i].point_index, reversed(face.wedge_indices)) points = (
points = [bm.verts[i] for i in point_indices] bm.verts[psk.wedges[face.wedge_indices[2]].point_index],
bm.verts[psk.wedges[face.wedge_indices[1]].point_index],
bm.verts[psk.wedges[face.wedge_indices[0]].point_index],
)
try: try:
bm_face = bm.faces.new(points) bm_face = bm.faces.new(points)
bm_face.material_index = face.material_index bm_face.material_index = face.material_index
@@ -182,40 +185,43 @@ def import_psk(psk: Psk, context: Context, name: str, options: PskImportOptions)
# Texture Coordinates # Texture Coordinates
uv_layer_data_index = 0 uv_layer_data_index = 0
uv_layer = mesh_data.uv_layers.new(name='UVMap') uv_layer_data = np.zeros((len(psk.faces) * 3, 2), dtype=np.float32)
for face_index, face in enumerate(psk.faces): for face_index, face in enumerate(psk.faces):
if face_index in invalid_face_indices: if face_index in invalid_face_indices:
continue continue
face_wedges = [psk.wedges[i] for i in reversed(face.wedge_indices)] for wedge in map(lambda i: psk.wedges[i], reversed(face.wedge_indices)):
for wedge in face_wedges: uv_layer_data[uv_layer_data_index] = wedge.u, 1.0 - wedge.v
uv_layer.data[uv_layer_data_index].uv = wedge.u, 1.0 - wedge.v
uv_layer_data_index += 1 uv_layer_data_index += 1
uv_layer = mesh_data.uv_layers.new(name='UVMap')
uv_layer.uv.foreach_set('vector', uv_layer_data.ravel())
# Extra UVs # Extra UVs
if psk.has_extra_uvs and options.should_import_extra_uvs: if psk.has_extra_uvs and options.should_import_extra_uvs:
extra_uv_channel_count = int(len(psk.extra_uvs) / len(psk.wedges)) extra_uv_channel_count = int(len(psk.extra_uvs) / len(psk.wedges))
wedge_index_offset = 0 wedge_index_offset = 0
uv_layer_data = np.zeros((len(psk.faces) * 3, 2), dtype=np.float32)
for extra_uv_index in range(extra_uv_channel_count): for extra_uv_index in range(extra_uv_channel_count):
uv_layer_data_index = 0 uv_layer_data_index = 0
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 invalid_face_indices: if face_index in invalid_face_indices:
continue continue
for wedge_index in reversed(face.wedge_indices): for wedge in map(lambda i: psk.wedges[i], reversed(face.wedge_indices)):
u, v = psk.extra_uvs[wedge_index_offset + wedge_index] uv_layer_data[uv_layer_data_index] = wedge.u, 1.0 - wedge.v
uv_layer.data[uv_layer_data_index].uv = u, 1.0 - v
uv_layer_data_index += 1 uv_layer_data_index += 1
wedge_index_offset += len(psk.wedges) wedge_index_offset += len(psk.wedges)
uv_layer = mesh_data.uv_layers.new(name=f'EXTRAUV{extra_uv_index}')
uv_layer.uv.foreach_set('vector', uv_layer_data.ravel())
# Vertex Colors # Vertex Colors
if psk.has_vertex_colors and options.should_import_vertex_colors: if psk.has_vertex_colors and options.should_import_vertex_colors:
# Convert vertex colors to sRGB if necessary.
psk_vertex_colors = np.zeros((len(psk.vertex_colors), 4)) psk_vertex_colors = np.zeros((len(psk.vertex_colors), 4))
for vertex_color_index in range(len(psk.vertex_colors)): for vertex_color_index in range(len(psk.vertex_colors)):
psk_vertex_colors[vertex_color_index,:] = psk.vertex_colors[vertex_color_index].normalized() psk_vertex_colors[vertex_color_index] = tuple(psk.vertex_colors[vertex_color_index])
psk_vertex_colors /= 255.0
# Convert vertex colors to sRGB if necessary.
if options.vertex_color_space == 'SRGBA': if options.vertex_color_space == 'SRGBA':
for i in range(psk_vertex_colors.shape[0]): psk_vertex_colors[:, :3] = np.vectorize(rgb_to_srgb)(psk_vertex_colors[:, :3])
psk_vertex_colors[i, :3] = tuple(map(lambda x: rgb_to_srgb(x), psk_vertex_colors[i, :3]))
# Map the PSK vertex colors to the face corners. # Map the PSK vertex colors to the face corners.
face_count = len(psk.faces) - len(invalid_face_indices) face_count = len(psk.faces) - len(invalid_face_indices)
@@ -230,7 +236,7 @@ def import_psk(psk: Psk, context: Context, name: str, options: PskImportOptions)
# Create the vertex color attribute. # Create the vertex color attribute.
face_corner_color_attribute = mesh_data.attributes.new(name='VERTEXCOLOR', type='FLOAT_COLOR', domain='CORNER') face_corner_color_attribute = mesh_data.attributes.new(name='VERTEXCOLOR', type='FLOAT_COLOR', domain='CORNER')
face_corner_color_attribute.data.foreach_set('color', face_corner_colors.flatten()) face_corner_color_attribute.data.foreach_set('color', face_corner_colors.ravel())
# Vertex Normals # Vertex Normals
if psk.has_vertex_normals and options.should_import_vertex_normals: if psk.has_vertex_normals and options.should_import_vertex_normals:

View File

@@ -17,13 +17,18 @@ class Color(Structure):
yield self.a yield self.a
def __eq__(self, other): def __eq__(self, other):
return all(map(lambda x: x[0] == x[1], zip(self, other))) return self.r == other.r and self.g == other.g and self.b == other.b and self.a == other.a
def __repr__(self): def __repr__(self):
return repr(tuple(self)) return repr(tuple(self))
def normalized(self) -> Tuple: def normalized(self) -> Tuple:
return tuple(map(lambda x: x / 255.0, iter(self))) return (
self.r / 255.0,
self.g / 255.0,
self.b / 255.0,
self.a / 255.0
)
class Vector2(Structure): class Vector2(Structure):

View File

@@ -7,11 +7,10 @@ from .data import Vector3, Quaternion
from ..shared.data import PsxBone from ..shared.data import PsxBone
def rgb_to_srgb(c: float): def rgb_to_srgb(c: float) -> float:
if c > 0.0031308: if c > 0.0031308:
return 1.055 * (pow(c, (1.0 / 2.4))) - 0.055 return 1.055 * (pow(c, (1.0 / 2.4))) - 0.055
else: return 12.92 * c
return 12.92 * c
def get_nla_strips_in_frame_range(animation_data: AnimData, frame_min: float, frame_max: float): def get_nla_strips_in_frame_range(animation_data: AnimData, frame_min: float, frame_max: float):