Fixed a bug where secondary UV layers would not be exported correctly if not all objects shared the same number of UV layers

This commit is contained in:
Colin Basnett
2024-12-22 18:14:22 -08:00
parent 324481d8d2
commit 34714099ce
2 changed files with 164 additions and 151 deletions

View File

@@ -62,23 +62,59 @@ def get_coordinate_system_transform(forward_axis: str = 'X', up_axis: str = 'Z')
def build_ase(context: Context, options: ASEBuildOptions, dfs_objects: Iterable[DfsObject]) -> ASE:
ase = ASE()
main_geometry_object = None
ase.materials = options.materials
dfs_objects = list(dfs_objects)
dfs_objects_processed = 0
context.window_manager.progress_begin(0, len(dfs_objects))
ase.materials = options.materials
class GeometryObjectInfo:
def __init__(self, name: str):
self.name = name
self.dfs_objects = []
main_geometry_object_info = GeometryObjectInfo('io_scene_ase')
geometry_object_infos: List[GeometryObjectInfo] = [
main_geometry_object_info,
]
for object_index, dfs_object in enumerate(dfs_objects):
if is_collision_name(dfs_object.obj.name):
geometry_object_info = GeometryObjectInfo(dfs_object.obj.name)
geometry_object_info.dfs_objects.append(dfs_object)
geometry_object_infos.append(geometry_object_info)
else:
main_geometry_object_info.dfs_objects.append(dfs_object)
# Sort the DFS objects into collision and non-collision objects.
coordinate_system_transform = get_coordinate_system_transform(options.forward_axis, options.up_axis)
for geometry_object_info in geometry_object_infos:
geometry_object = ASEGeometryObject()
geometry_object.name = geometry_object_info.name
if geometry_object.is_collision:
# Test that collision meshes are manifold and convex.
bm = bmesh.new()
bm.from_mesh(mesh_object.data)
for edge in bm.edges:
if not edge.is_manifold:
del bm
raise ASEBuildError(f'Collision mesh \'{obj.name}\' is not manifold')
if not edge.is_convex:
del bm
raise ASEBuildError(f'Collision mesh \'{obj.name}\' is not convex')
max_uv_layers = 0
for dfs_object in dfs_objects:
for dfs_object in geometry_object_info.dfs_objects:
mesh_data = cast(Mesh, dfs_object.obj.data)
max_uv_layers = max(max_uv_layers, len(mesh_data.uv_layers))
coordinate_system_transform = get_coordinate_system_transform(options.forward_axis, options.up_axis)
geometry_object.uv_layers = [ASEUVLayer() for _ in range(max_uv_layers)]
print('max_uv_layers', max_uv_layers)
for object_index, dfs_object in enumerate(dfs_objects):
for dfs_object in geometry_object_info.dfs_objects:
obj = dfs_object.obj
matrix_world = dfs_object.matrix_world
@@ -100,27 +136,6 @@ def build_ase(context: Context, options: ASEBuildOptions, dfs_objects: Iterable[
mesh_object = bpy.data.objects.new('', mesh_data)
mesh_object.matrix_world = matrix_world
if not is_collision_name(obj.name) and main_geometry_object is not None:
geometry_object = main_geometry_object
else:
geometry_object = ASEGeometryObject()
geometry_object.name = obj.name
if not geometry_object.is_collision:
main_geometry_object = geometry_object
ase.geometry_objects.append(geometry_object)
if geometry_object.is_collision:
# Test that collision meshes are manifold and convex.
bm = bmesh.new()
bm.from_mesh(mesh_object.data)
for edge in bm.edges:
if not edge.is_manifold:
del bm
raise ASEBuildError(f'Collision mesh \'{obj.name}\' is not manifold')
if not edge.is_convex:
del bm
raise ASEBuildError(f'Collision mesh \'{obj.name}\' is not convex')
vertex_transform = Matrix.Rotation(math.pi, 4, 'Z') @ Matrix.Scale(options.scale, 4) @ matrix_world
for vertex_index, vertex in enumerate(mesh_data.vertices):
@@ -202,19 +217,16 @@ def build_ase(context: Context, options: ASEBuildOptions, dfs_objects: Iterable[
# Texture Coordinates
for i, uv_layer_data in enumerate([x.data for x in mesh_data.uv_layers]):
if i >= len(geometry_object.uv_layers):
geometry_object.uv_layers.append(ASEUVLayer())
uv_layer = geometry_object.uv_layers[i]
for loop_index, loop in enumerate(mesh_data.loops):
u, v = uv_layer_data[loop_index].uv
uv_layer.texture_vertices.append((u, v, 0.0))
# Add zeroed texture vertices for any missing UV layers.
for i in range(len(geometry_object.uv_layers), max_uv_layers):
uv_layer = ASEUVLayer()
for i in range(len(mesh_data.uv_layers), max_uv_layers):
uv_layer = geometry_object.uv_layers[i]
for _ in mesh_data.loops:
uv_layer.texture_vertices.append((0.0, 0.0, 0.0))
geometry_object.uv_layers.append(uv_layer)
# Texture Faces
for loop_triangle in mesh_data.loop_triangles:
@@ -246,14 +258,14 @@ def build_ase(context: Context, options: ASEBuildOptions, dfs_objects: Iterable[
geometry_object.texture_vertex_offset += len(mesh_data.loops)
geometry_object.vertex_offset = len(geometry_object.vertices)
context.window_manager.progress_update(object_index)
dfs_objects_processed += 1
context.window_manager.progress_update(dfs_objects_processed)
ase.geometry_objects.append(geometry_object)
context.window_manager.progress_end()
if len(ase.geometry_objects) == 0:
raise ASEBuildError('At least one mesh object must be selected')
if main_geometry_object is None:
raise ASEBuildError('At least one non-collision mesh must be exported')
return ase

View File

@@ -231,10 +231,11 @@ class ASE_UL_materials(UIList):
row.prop(item.material, 'name', text='', emboss=False, icon_value=layout.icon(item.material))
class ASE_UL_strings(UIList):
class ASE_UL_material_names(UIList):
def draw_item(self, context, layout, data, item, icon, active_data, active_propname, index):
row = layout.row()
row.prop(item, 'string', text='', emboss=False)
material = bpy.data.materials.get(item.string, None)
row.prop(item, 'string', text='', emboss=False, icon_value=layout.icon(material) if material is not None else 0)
@@ -491,7 +492,7 @@ class ASE_OT_export_collection(Operator, ExportHelper):
if materials_panel:
row = materials_panel.row()
row.template_list('ASE_UL_strings', '', self, 'material_order', self, 'material_order_index')
row.template_list('ASE_UL_material_names', '', self, 'material_order', self, 'material_order_index')
col = row.column(align=True)
col.operator(ASE_OT_material_order_add.bl_idname, icon='ADD', text='')
col.operator(ASE_OT_material_order_remove.bl_idname, icon='REMOVE', text='')
@@ -588,7 +589,7 @@ classes = (
ASE_PG_material,
ASE_PG_string,
ASE_UL_materials,
ASE_UL_strings,
ASE_UL_material_names,
ASE_PG_export,
ASE_OT_export,
ASE_OT_export_collection,