Skip to content

Commit

Permalink
Improved PSK vertex color importing to be per-corner instead of per-v…
Browse files Browse the repository at this point in the history
…ertex

Previously, the importer was storing the vertex colors in the point
domain. However, the PSK itself stores colors per "wedge", which maps
to corners, resulting in the "ambiguous vertex colors" warning if two
corners mapped to the same vertex but had different colors.

The new method is now more correct and doesn't discard data.
  • Loading branch information
cmbasnett committed Jan 22, 2024
1 parent 3d3bbb9 commit b2f5985
Showing 1 changed file with 24 additions and 29 deletions.
53 changes: 24 additions & 29 deletions io_scene_psk_psa/psk/importer.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
from math import inf
from typing import Optional, List

import bmesh
Expand All @@ -17,7 +16,7 @@ def __init__(self):
self.should_import_mesh = True
self.should_reuse_materials = True
self.should_import_vertex_colors = True
self.vertex_color_space = 'sRGB'
self.vertex_color_space = 'SRGB'
self.should_import_vertex_normals = True
self.should_import_extra_uvs = True
self.should_import_skeleton = True
Expand Down Expand Up @@ -144,6 +143,7 @@ def import_psk(psk: Psk, context, options: PskImportOptions) -> PskImportResult:

bm.verts.ensure_lookup_table()

# FACES
invalid_face_indices = set()
for face_index, face in enumerate(psk.faces):
point_indices = map(lambda i: psk.wedges[i].point_index, reversed(face.wedge_indices))
Expand Down Expand Up @@ -192,33 +192,28 @@ def import_psk(psk: Psk, context, options: PskImportOptions) -> PskImportResult:

# VERTEX COLORS
if psk.has_vertex_colors and options.should_import_vertex_colors:
size = (len(psk.points), 4)
vertex_colors = np.full(size, inf)
vertex_color_data = mesh_data.vertex_colors.new(name='VERTEXCOLOR')
ambiguous_vertex_color_point_indices = []

for wedge_index, wedge in enumerate(psk.wedges):
point_index = wedge.point_index
psk_vertex_color = psk.vertex_colors[wedge_index].normalized()
if vertex_colors[point_index, 0] != inf and tuple(vertex_colors[point_index]) != psk_vertex_color:
ambiguous_vertex_color_point_indices.append(point_index)
else:
vertex_colors[point_index] = psk_vertex_color

if options.vertex_color_space == 'SRGBA':
for i in range(vertex_colors.shape[0]):
vertex_colors[i, :3] = tuple(map(lambda x: rgb_to_srgb(x), vertex_colors[i, :3]))

for loop_index, loop in enumerate(mesh_data.loops):
vertex_color = vertex_colors[loop.vertex_index]
if vertex_color is not None:
vertex_color_data.data[loop_index].color = vertex_color
else:
vertex_color_data.data[loop_index].color = 1.0, 1.0, 1.0, 1.0

if len(ambiguous_vertex_color_point_indices) > 0:
result.warnings.append(
f'{len(ambiguous_vertex_color_point_indices)} vertex(es) with ambiguous vertex colors.')
# Convert vertex colors to sRGB if necessary.
psk_vertex_colors = np.zeros((len(psk.vertex_colors), 4))
for i in range(len(psk.vertex_colors)):
psk_vertex_colors[i,:] = psk.vertex_colors[i].normalized()
match options.vertex_color_space:
case 'SRGBA':
for i in range(psk_vertex_colors.shape[0]):
psk_vertex_colors[i, :3] = tuple(map(lambda x: rgb_to_srgb(x), psk_vertex_colors[i, :3]))
case _:
pass

# Map the PSK vertex colors to the face corners.
face_corner_colors = np.full((len(psk.faces * 3), 4), 1.0)
face_corner_color_index = 0
for face_index, face in enumerate(psk.faces):
for wedge_index in reversed(face.wedge_indices):
face_corner_colors[face_corner_color_index] = psk_vertex_colors[wedge_index]
face_corner_color_index += 1

# Create the vertex color attribute.
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())

# VERTEX NORMALS
if psk.has_vertex_normals and options.should_import_vertex_normals:
Expand Down

0 comments on commit b2f5985

Please sign in to comment.